面试经典150题0524
Leetcode002 两数相加
- 判断两个链表是否有一个为空,为空则直接返回另一个链表
- 同时处理两个节点相同位置的节点,并使用一个
next
保存进位信息。 - 处理到一个链表为空时,只循环处理另外一个链表即可,需要考虑可能存在的进位。
- 当两个链表都处理完后,需要判断是否还存在进位,如果存在则需要新建一个节点保存。
class Solution {
public ListNode addTwoNumbers(ListNode l1, ListNode l2) {
if(l1 == null){
return l2;
}
if(l2 == null){
return l1;
}
int next = 0;
ListNode head = new ListNode();
ListNode curr = head;
while (l1 != null && l2 != null){
ListNode currNode = new ListNode();
int val = l1.val + l2.val + next;
currNode.val = val % 10;
curr.next = currNode;
curr = currNode;
next = val / 10;
l1 = l1.next;
l2 = l2.next;
}
while (l1 != null){
ListNode currNode = new ListNode();
int val = l1.val + next;
next = val / 10;
currNode.val = val % 10;
curr.next = currNode;
curr = currNode;
l1 = l1.next;
}
while (l2 != null){
ListNode currNode = new ListNode();
int val = l2.val + next;
next = val / 10;
currNode.val = val % 10;
curr.next = currNode;
curr = currNode;
l2 = l2.next;
}
if(next == 1){
curr.next = new ListNode(1);
}
return head.next;
}
}
Leetcode021 合并两个有序链表
原地操作两个链表的指针,优先串联节点值小的节点。如果最后有一个链表遍历完,直接将另一个链表未遍历的节点串联到尾部即可。
public ListNode mergeTwoLists(ListNode l1, ListNode l2) {
if(l1 == null){
return l2;
}
if(l2 == null){
return l1;
}
ListNode res = new ListNode();
ListNode head = res;
while (l1 != null && l2 != null){
if(l1.val <= l2.val){
res.next = l1;
l1 = l1.next;
res = res.next;
}
else {
res.next = l2;
l2 = l2.next;
res = res.next;
}
}
if(l1 != null){
res.next = l1;
}
if(l2 != null){
res.next = l2;
}
return head.next;
}
Leetcode138 随机链表的复制
遍历原来链表,创建新节点复制源节点的值,同时将原节点和新节点保存到HashMap
中,在第一轮遍历中同时确定新节点的next
指针。
当所有的节点创建出来后,map.get(curr).random = map.get(curr.random)
通过HashMap
填充新节点中的random
指针。
public Node copyRandomList(Node head) {
if(head == null){
return head;
}
Node curr = head;
Node copyHead = new Node(0);
Node copyCurr = copyHead;
Map<Node, Node> map = new HashMap<>();
while (curr != null){
Node node = new Node(curr.val);
copyCurr.next = node;
copyCurr = copyCurr.next;
map.put(curr, node);
curr = curr.next;
}
curr = head;
while (curr != null){
map.get(curr).random = map.get(curr.random);
curr = curr.next;
}
return copyHead.next;
}
Leetcode092 反转链表Ⅱ
-
添加一个头节点,方便处理
-
先处理
left
左边的节点,直接遍历即可,但是要保存left
左边最后一个节点。 -
然后处理
right-left+1
个待反转的元素,定义两个指针pre
和curr
分别存放当前遍历节点和前一个节点。没节点之间指针反转时,需要一个临时变量保存curr
的下一个节点。ListNode nextNode = curr.next; curr.next = pre; pre = curr; curr = nextNode;
-
处理完需要反转的节点,然后需要将原来
left
左边最后一个节点的下一个节点的next
指向curr
节点,也就是连接到right
后面的第一个节点;另外将left
左边最后一个节点的next
指针指向pre
节点,即第right
个节点。
public static ListNode reverseBetween(ListNode head, int left, int right) {
// 一趟扫描完成反转
ListNode dummy = new ListNode(0, head);
ListNode ptr = dummy;
for(int i = 1; i < left; i++){
ptr = ptr.next;
}
ListNode pre = null;
ListNode curr = ptr.next;
for (int i = 0; i < right - left + 1; i++) {
ListNode nextNode = curr.next;
curr.next = pre;
pre = curr;
curr = nextNode;
}
ptr.next.next = curr;
ptr.next = pre;
return dummy.next;
}
e = curr.next;
curr.next = pre;
pre = curr;
curr = nextNode;
}
ptr.next.next = curr;
ptr.next = pre;
return dummy.next;
}