LeetCode算法问题1 —— Add Two Numbers
来源:互联网 发布:淘宝网站策划 编辑:程序博客网 时间:2024/05/29 15:01
最近在学校提供网站LeetCode上刷算法题,近段时间会将一些自己觉得有意义,值得效仿的点写下来,为自己以后的工作和学习所用。
今天讲的是Add Two Numbers
首先看一下问题描述
问题大概意思是这样的:分别将两个非负整数的各个数位用链表连接起来,且数字的存储方向是反向的,即,2->4->3其实是342。要求我们计算出两个整数的和并以相同方式返回。
同时,题目提供了这种链式的数据结构
struct ListNode { int val; ListNode *next; ListNode(int x) : val(x), next(NULL) {}};
刚读问题的时候我就在想:为什么要把数反向存储?后来拿了几个数试验了一下发现了这个的好处。以2->0->7(702)、8->0->8(808)为例,自然702+808=1510,按照我们正常的思维来顺序存储的话,那么运算必须从右往左,这是因为我们在没有计算低位的时候永远不知道是否会向高位进位,这就意味着我们必须先把指针移到末尾,然后再去逐个找父节点,这是ListNode这个数据结构无法实现的,同时也做了很多无用功(从开头将最高位指针移到末尾最低位指针)。
而反向存储完美地规避了这些问题,它本身初始节点就是最低位,这是我觉得这个问题设计得比较巧妙的点睛之笔,只是调换了个顺序,问题难度瞬间降下来了。
下面说一下我对这个问题的解决思想。很简单,遍历两个数列,一个变量sum记录对应位相加结果,一个变量carry记录进位,将sum取个位数作为这两个位相加的结果。遍历数列l1, l2最终会得到三个结果:
- l1,l2长度相同,同时遍历完
- l1先遍历完,l2较长
- l2先遍历完,l1较长
一开始我思想比较死板,严格将每种情况都用if语句乖乖地写下来了,但是现在我却想说:“管他呢!”。哪个先遍历完,就把它的指针设为NULL,在两个数列都没遍历完(不都是NULL)之前,sum只加上非NULL指针的val值就行了。最后等把两个数列都遍历完后,再看看是否产生了更高的进位即可。
现在思路清楚了,首先做准备工作
其实没必要设置ptr1,ptr2的,直接对参数取next也是可以的,因为这里是参数的副本,在这里的操作对参数本身是没有任何影响的,但是我觉得还是养成不碰参数的习惯较好。ptrForAnswer是为了扩展answer而准备的,最后函数结束返回answer即可。
接下来可以确定循环了
如何规避数列长度不一的情况呢,这是我自认为做得比较好的办法:
int sum = carry;if (ptr1) { sum += ptr1->val; ptr1 = ptr1->next; }if (ptr2) { sum += ptr2->val; ptr2 = ptr2->next; }
if语句做了两件事情,一、将数列指针移向下一位(有下一位的前提下);二、把该位的值并入了sum中(该数列存在这一位的前提下)。
将两个数列都遍历完后,该考虑是否最后还产生了一个进位,这很简单
如此这一个问题就解决了。速度也还不错。这个算法复杂度主要看参数l1,l2的长度,因此是O(n)。
个人而言,这个问题有两个亮点,第一就是它的反向存储,第二就是我对数列长度不一的问题的优化。详细可以看下面的源代码。
/* 问题描述 两个链式非负整数,存储是反方向的。 如4->3->2其实是234,要求计算出两个链式数据的和, 并按相同存储方式返回 *//* From https://leetcode.com/problems/add-two-numbers/description/ *//* 2017-09-07 by 王世祺 *//* build the struct ListNode */#include<iostream>using namespace std;struct ListNode { int val; ListNode *next; ListNode(int x) : val(x), next(NULL) {}};ListNode* addTwoNumbers(ListNode* l1, ListNode* l2) { int carry = 0; ListNode* ptr1 = l1->next; ListNode* ptr2 = l2->next; ListNode* answer = new ListNode((l1->val + l2->val) % 10); ListNode* ptrForAnswer = answer; carry = (l1->val + l2->val) >= 10 ? 1 : 0; /* 在两个数长度不一样的时候,和计算只在相同长度范围内有效。 */ while (ptr1 || ptr2) { int sum = carry; if (ptr1) { sum += ptr1->val; ptr1 = ptr1->next; } if (ptr2) { sum += ptr2->val; ptr2 = ptr2->next; } ptrForAnswer->next = new ListNode(sum % 10); carry = (sum) >= 10 ? 1 : 0; ptrForAnswer = ptrForAnswer->next; } /* 结束,看是否有进位 */ if (carry == 1) ptrForAnswer->next = new ListNode(1); return answer;}int main() { ListNode* l1 = new ListNode(3); l1->next = new ListNode(7); ListNode* l2 = new ListNode(9); l2->next = new ListNode(2); addTwoNumbers(l1, l2);}
- LeetCode算法问题1 —— Add Two Numbers
- leetcode—Add Two Numbers
- LeetCode算法题——Add Two Numbers
- (LeetCode)算法题目——Add Two Numbers
- LeetCode —— Add Two Numbers
- LeetCode——Add Two Numbers
- LeetCode——Add Two Numbers
- leetcode 002 —— add two numbers
- LeetCode——Add Two Numbers
- LeetCode——Add Two Numbers
- #2 LeetCode——Add Two Numbers
- LeetCode——Add Two Numbers
- leetcode——Add Two Numbers
- leetcode——2Add Two Numbers
- LeetCode——2. Add Two Numbers
- Leetcode——2. Add Two Numbers
- LeetCode——2. Add Two Numbers
- LeetCode——add two numbers
- Spark算子补充<一>
- Java中的线程的状态与生命周期
- C++调用空指针对象的成员函数成功的理解
- SEO网站性能优化
- python TypeError: 'module' object is not callable
- LeetCode算法问题1 —— Add Two Numbers
- 2017.9.7 骑士 思考记录
- tomcat7.0下jndi的三种配置方式
- mongodb学习(一):centos下安装mongodb
- Centos7常用的一些命令
- 大数据计算的四支精干队伍,你造吗
- VPS配置Git Hooks实现hexo博客更新
- Android studio 中的gradle粗解
- ssh 登录出现的几种错误以及解决办法