由于做提前连链表是怎么实现的都不知道所以补了点课。
Single Linked List 代码来自这位兄台
pasilo
https://blog.51cto.com/13047263/2070815
内容理解我看的知乎,但是其实我都还没有独立实现一个python链表,深浅拷贝啥的很晕。做这个题简直坐飞机。
如何更好的理解链表
以下代码和LeetCode上面的链表稍微有些许不同,那个里面链表和链表上面的节点是相同的类。而这边抽象出了链表节点和链表本身两个类。毕竟这段代码实现了更多链表方法。单用一个Node类不太容易做到了。需要注意的就是实现层面current是一个节点类的指针,指示当前的Node最终就是尾部,head也是一个节点类的指针,指示头部Node。
lass Node {
private int val; // node value
private Node next; // next node location
public Node() {
}
// constructor to construct node value and next node RAM location
public Node(int data) {
this.val = data;
this.next = new Node();
}
public int getData() {
return this.val;
}
// change data value
public void setData(int value) {
this.val = value;
}
// get next node location
public Node getNext() {
return this.next;
}
// generate new node with new value
public void setNewNext(int value) {
// Node newNode = new Node(value);
this.next = new Node(value);
}
// set next node with a generated node instance
public void setNext(Node node) {
this.next = node;
}
}
public class SingleLinkedList {
private Node head;
private Node current;
// current is a pointer for node
// set head node with value
// set head node with location of next node
public SingleLinkedList(int data) {
this.head = new Node(data);
current = head;
}
// set next node with value
// set next node with location of next node
public void append(int value) {
current.setNewNext(value);
current = current.getNext();
}
public void remove(int destation) {
Node pointer = this.head;
for (int i = 0; i < destation - 1; i++) {
pointer = pointer.getNext();
}
// jump over node at the position of destation
Node temp = pointer.getNext().getNext();
pointer.setNext(temp);
}
public void insert(int destation, int value) {
Node pointer = this.head;
for (int i = 0; i < destation - 1; i++) {
pointer = pointer.getNext();
}
Node temp = pointer.getNext();
Node newNode = new Node(value);
pointer.setNext(newNode);
newNode.setNext(temp);
}
// get the value of node at locatio
public int at(int index) {
Node pointer = this.head;
for (int i = 0; i < index; i++) {
pointer = pointer.getNext();
}
return pointer.getData();
}
// print out the linked data
public void display() {
Node pointer = this.head;
// pointer move from head to the tail
// current is the tail node
while (current != pointer) {
System.out.printf("%d->", pointer.getData());
pointer = pointer.getNext();
}
System.out.println(pointer.getData());
System.out.println("this is the end.\n");
}
public int size() {
int size = 1;
Node pointer = this.head;
while (current != pointer) {
pointer = pointer.getNext();
size++;
}
return size;
}
public static void main(String[] args) {
// TODO Auto-generated method stub
SingleLinkedList l1 = new SingleLinkedList(0);
l1.append(1);
l1.display();
SingleLinkedList l2 = new SingleLinkedList(0);
l2.append(1);
l2.append(2);
l2.display();
}
}
public ListNode addTwoNumbers(ListNode l1, ListNode l2) {
ListNode dummyHead = new ListNode(0);
ListNode p = l1, q = l2, curr = dummyHead;
int carry = 0;
while (p != null || q != null) {
int x = (p != null) ? p.val : 0;
int y = (q != null) ? q.val : 0;
int sum = carry + x + y;
carry = sum / 10;
curr.next = new ListNode(sum % 10);
curr = curr.next;
if (p != null) p = p.next;
if (q != null) q = q.next;
}
if (carry > 0) {
curr.next = new ListNode(carry);
}
return dummyHead.next;
}
https://leetcode-cn.com/problems/two-sum/solution/liang-shu-xiang-jia-by-
def addTwoNumbers(self, l1: ListNode, l2: ListNode) -> ListNode:
head = ListNode(0)
# curr is the dummy linked list
curr = head
carry = 0
while l1 or l2:
x = l1.val if l1 else 0
y = l2.val if l2 else 0
sum = x + y + carry
carry = sum // 10
curr.next = ListNode(sum % 10)
# pointer move to the next node
curr = curr.next
if l1:
l1 = l1.next
if l2:
l2 = l2.next
# finally there need to carry
if (carry > 0):
curr.next = ListNode(1)
return head.next
稍微改改就能实现一个python化的版本。但是老实说就算是改写,这里面也太容易出错了因为细节实在是太多了。代码虽然短但是里面琐碎的细节真心多。
head = ListNode(0)
# 注意这个哑节点的值根本就不会被用到,next才开始记录两数之和
curr = head
carry = 0
while l1 or l2:
x = l1.val if l1 else 0
y = l2.val if l2 else 0
sum = x + y + carry
carry = sum // 10
curr.next = ListNode(sum % 10)
curr = curr.next
if l1:l1 = l1.next
if l2:l2 = l2.next
5.注意最后一轮运算后我们的通过sum运算进位的机制没有了,所以需要手动进位下。最后的答案是哑结点指向的结点
if (carry > 0):
curr.next = ListNode(1)
return head.next
暴力求解
原方法地址 https://blog.csdn.net/fuxuemingzhu/article/details/79379626
class Solution(object):
def addTwoNumbers(self, l1, l2):
"""
:type l1: ListNode
:type l2: ListNode
:rtype: ListNode
"""
num1 = ''
num2 = ''
while l1:
num1 += str(l1.val)
l1 = l1.next
while l2:
num2 += str(l2.val)
l2 = l2.next
add = str(int(num1[::-1]) + int(num2[::-1]))[::-1]
head = ListNode(add[0])
answer = head
for i in range(1, len(add)):
node = ListNode(add[i])
head.next = node
head = head.next
return answer
这个解太妙了,同时解决进位和补位问题,但是python递归好麻烦。addTwoNumbers不能递归自己。平白无故多了几个步骤。
class Solution:
def addTwoNumbers(self, l1, l2):
"""
:type l1: ListNode
:type l2: ListNode
:rtype: ListNode
"""
def addIter(l1, l2):
if not l1: return l2
if not l2: return l1
sum = l1.val + l2.val
res = ListNode(sum % 10)
res.next = addIter(l1.next, l2.next)
if sum >= 10:
res.next = addIter(res.next, ListNode(1))
return res
res = addIter(l1,l2)
return res
再来看看楼上那位的C++版本,明显优秀一些。
/**
* Definition for singly-linked list.
* struct ListNode {
* int val;
* ListNode *next;
* ListNode(int x) : val(x), next(NULL) {}
* };
*/
class Solution {
public:
ListNode* addTwoNumbers(ListNode* l1, ListNode* l2) {
if (!l1) return l2;
if (!l2) return l1;
int target = l1->val + l2->val;
ListNode* res = new ListNode(target % 10);
res->next = addTwoNumbers(l1->next, l2->next);
if (target >= 10)
res->next = addTwoNumbers(res->next, new ListNode(1));
delete l1, l2;
return res;
}
};