这道题还真没什么好办法。
最直接的做法就是直接同时遍历两个链表,然后每两个对应的值相加,超过10就进位,不过在写的过程中还是会遇到很多麻烦。以及最后遍历完两个链表后若还产生进位的细节问题。
这道题有个很巧妙的地方:就是用head和tail标记了链表的头和尾。
public ListNode addTwoNumbers(ListNode l1, ListNode l2) {
ListNode head = null;
ListNode tail = null;
int bit = 0;
while (l1 != null || l2 != null) {
int n1 = l1 == null ? 0 : l1.val;
int n2 = l2 == null ? 0 : l2.val;
int sum = n1 + n2 + bit;
if (head == null) {
head = tail = new ListNode(sum % 10);
} else {
tail.next = new ListNode(sum % 10);
tail = tail.next;
}
bit = sum / 10;
if (l1 != null) {
l1 = l1.next;
}
if (l2 != null) {
l2 = l2.next;
}
}
if (bit > 0) {
tail.next = new ListNode(bit);
}
return head;
}
public boolean hasCycle(ListNode head) {
if(head == null || head.next == null) {
return false;
}
ListNode slow = head;
ListNode fast = head;
while(fast.next != null && fast.next.next != null) {
slow = slow.next;
fast = fast.next.next;
if(slow == fast) {
return true;
}
}
return false;
}
这道题的总结:如果有判断 fast.next.next为null的地方,必须提前判断fast.next不为null。
做完这道题后,开心地去提交,发现过了,运行时间上击败3.14%的人。打开官方答案一看,我真是白痴。
我的做法是:遍历这个链表。用一个栈把小于x的节点记录下来,然后,遍历完,在依次弹出来,按顺序往前链接节点。
public ListNode partition(ListNode head, int x) {
ListNode dumy = new ListNode(-1, head);
ListNode cur = dumy;
Stack<ListNode> stack = new Stack<>();
while (cur.next != null) {
if (cur.next.val < x) {
stack.push(cur.next);
cur.next = cur.next.next;
} else {
cur = cur.next;
}
}
while (!stack.isEmpty()) {
ListNode pop = stack.pop();
pop.next = dumy.next;
dumy.next = pop;
}
return dumy.next;
}
答案的做法是:遍历的时候把比x大的和小的节点分类组成新的链表,然后再把它们接上。
public ListNode partition(ListNode head, int x) {
ListNode smallHead = new ListNode(-1);
ListNode small = smallHead;
ListNode largeHead = new ListNode(-1);
ListNode large = largeHead;
while (head != null) {
if (head.val < x) {
small.next = head;
small = small.next;
} else {
large.next = head;
large = large.next;
}
head = head.next;
}
large.next = null;
small.next = largeHead.next;
return smallHead.next;
}
这个题没说的,多做几遍吧。
单向链表:
class MyLinkedList {
int size;
ListNode head;
public MyLinkedList() {
this.size = 0;
this.head = new ListNode(0);
}
public int get(int index) {
if(index < 0 || index >= size) {
return -1;
}
ListNode cur = head;
for(int i = 0; i <= index; i++) {
cur = cur.next;
}
return cur.val;
}
public void addAtHead(int val) {
addAtIndex(0, val);
}
public void addAtTail(int val) {
addAtIndex(size, val);
}
public void addAtIndex(int index, int val) {
if(index > size) {
return;
}
ListNode cur = head;
index = Math.max(0, index);
for(int i = 0; i < index ; i++) {
cur = cur.next;
}
ListNode add = new ListNode(val);
add.next = cur.next;
cur.next = add;
size++;
}
public void deleteAtIndex(int index) {
if(index < 0 || index >= size) {
return;
}
ListNode cur = head;
for(int i = 0; i < index; i++) {
cur = cur.next;
}
cur.next = cur.next.next;
size--;
}
class ListNode {
int val;
ListNode next;
public ListNode(int val) {
this.val = val;
}
}
}
双向链表
双向链表的方法,为了提升效率,获取节点以及增加节点时都是从两端双向进行的。
class MyLinkedList {
int size;
ListNode head;
ListNode tail;
public MyLinkedList() {
this.size = 0;
head = new ListNode(0);
tail = new ListNode(0);
head.next = tail;
tail.prev = head;
}
public int get(int index) {
if(index >= size || index < 0) {
return -1;
}
ListNode cur;
if(index < size - index) {
cur = head;
for(int i = 0; i <= index; i++) {
cur = cur.next;
}
} else {
cur = tail;
for(int i = 0; i < size - index; i++) {
cur = cur.prev;
}
}
return cur.val;
}
public void addAtHead(int val) {
addAtIndex(0, val);
}
public void addAtTail(int val) {
addAtIndex(size, val);
}
public void addAtIndex(int index, int val) {
if(index > size) {
return;
}
index = Math.max(0, index);
ListNode pre, last;
if(index < size - index) {
pre = head;
for(int i = 0; i < index; i++) {
pre = pre.next;
}
last = pre.next;
} else {
last = tail;
for(int i = 0; i < size -index; i++) {
last = last.prev;
}
pre = last.prev;
}
size++;
ListNode node = new ListNode(val);
pre.next = node;
node.prev = pre;
last.prev = node;
node.next = last;
}
public void deleteAtIndex(int index) {
if(index >= size || index < 0) {
return;
}
ListNode pre, last;
if(index < size - index) {
pre = head;
for(int i = 0; i < index; i++) {
pre = pre.next;
}
last = pre.next.next;
} else {
last = tail;
for(int i = 0; i < size - index - 1; i++) {
last = last.prev;
}
pre = last.prev.prev;
}
size--;
pre.next = last;
last.prev = pre;
}
class ListNode {
int val;
ListNode next;
ListNode prev;
public ListNode(int val) {
this.val = val;
}
}
}