2个非空链表相加,里面的元素都是int类型,
比如 (3->4->1) + (1->2) ,返回4->6->1. 第一位是最低位
面试官想要的思路,在链表中挨个处理单个元素,需要注意进位的情况. 考察下链表的熟练程度和特殊情况的处理.
// 在链表中处理,挨个处理每个元素,需注意进位,和最后一位进位的情况,
// 效率上略高,O(最长的链表)但是读起来没有第一种好理解
class Solution {
func addTwoNumbers(_ l1: ListNode?, _ l2: ListNode?) -> ListNode? {
guard l1 != nil else {
return l2
}
guard l2 != nil else {
return l1
}
// 占位节点,方便书写代码
let result = ListNode.init(0)
var workNode = result
var overFlow = 0 // 是否有进位标志
var first = l1
var second = l2
while first != nil || second != nil || overFlow != 0 {
var firstVal = 0
if first != nil {
firstVal = first!.val
}
var secondVal = 0
if second != nil {
secondVal = second!.val
}
var val = firstVal + secondVal + overFlow
if val>=10 {
val -= 10
overFlow = 1
} else {
overFlow = 0
}
let temp = ListNode.init(val)
workNode.next = temp
workNode = temp
first = first?.next
second = second?.next
}
return result.next
}
}
下面还有一个类似的题目,
2个非空链表相加,里面的元素都是int类型,
比如 (3->4->1) + (1->2) ,返回3->5->3,
这个题目和上面有点小不同, 把第一位认为是最高位, 可以用2个栈保存链表, 然后同时pop,这个可以保证pop出来的是同一位, 加出来的结果也加入到一个栈中, 然后在把结果栈转成链表返回即可.
class Solution {
func addTwoNumbers(_ l1: ListNode?, _ l2: ListNode?) -> ListNode? {
guard l1 != nil else {
return l2
}
guard l2 != nil else {
return l1
}
var firstArray = [Int]()
var secondArray = [Int]()
var first = l1
var second = l2
while first != nil {
firstArray.append(first!.val)
first = first?.next
}
while second != nil {
secondArray.append(second!.val)
second = second?.next
}
var resultArray = [Int]()
var overFlow = 0
while firstArray.count > 0 || secondArray.count > 0 || overFlow != 0 {
let firstVal = firstArray.popLast() ?? 0
let secondVal = secondArray.popLast() ?? 0
var val = firstVal + secondVal + overFlow
if val>=10 {
val -= 10
overFlow = 1
} else {
overFlow = 0
}
resultArray.append(val)
}
let result = ListNode.init(0)
var workNode = result
while resultArray.count > 0 {
let temp = ListNode.init(resultArray.popLast()!)
workNode.next = temp
workNode = temp
}
return result.next
}
}
发现竟然不是100%, 后续看了看其他人的代码, 确实存在优化的空间, 最后一个结果栈, 其实是没有必要的, 可以一边计算出结果,一边生成结果链表. 这样操作后可以节省一次循环的时间, 优化后就是超过100%了
var result : ListNode!
var temp : ListNode!
var overFlow = 0
while firstArray.count > 0 || secondArray.count > 0 || overFlow != 0 {
// 省略代码...... 还是原来的计算val
// 此处不需要结果栈了, 用temp保存结果链表的上一个节点, 然后串起来, 节省了一次循环的时间
result = ListNode.init(val)
if temp != nil {
result.next = temp
}
temp = result
}
return result
除了常规解法, 还可以这样, 遍历把链表中的数据用一个真正的int表示出来, 然后2个int相加的结果为sum,在把sum转成一个链表输出.这个方案不用考虑那么多细节,进位啊,最后一位超出了处理啊统统不需要考虑. 简单直接, 但是慢一点点,而且不能处理超大数,不论是用处long还是int,对于位数过多的数字总是能超出使用范围导致无法处理的, 这个当然是无法通过测试用例的, 给出第一位是最低位的解法.
// 把链表的数据转出来,然后处理,需要O(m+n+最长的链表)
void fun1() {
NSArray * first = @[@(1),@(5),@(9),@(6)];
NSArray * second = @[@(3),@(9),@(2),@(4)];
int firstInt = 0;
for (int i = 0; i<first.count; i++) {
NSNumber * num = first[i];
firstInt += num.intValue * pow(10, i);
}
NSLog(@"第一个:%d",firstInt);
int secondInt = 0;
for (int i = 0; i<second.count; i++) {
NSNumber * num = second[i];
secondInt += num.intValue * pow(10, i);
}
NSLog(@"第二个:%d",secondInt);
int sum = firstInt + secondInt;
NSLog(@"结果:%d",sum);
NSMutableArray * result = [[NSMutableArray alloc] init];
while (sum>0) {
[result addObject:@(sum%10)];
sum = sum/10;
}
NSLog(@"%@",result);
}