我是
方圆
。
“无他,唯手熟尔”
2. 两数相加
给出两个 非空 的链表用来表示两个非负的整数。其中,它们各自的位数是按照 逆序 的方式存储的,并且它们的每个节点只能存储 一位 数字。
如果,我们将这两个数相加起来,则会返回一个新的链表来表示它们的和。
您可以假设除了数字 0 之外,这两个数都不会以 0 开头。
示例:
输入:(2 -> 4 -> 3) + (5 -> 6 -> 4)
输出:7 -> 0 -> 8
原因:342 + 465 = 807
class Solution {
public ListNode addTwoNumbers(ListNode l1, ListNode l2) {
//神奇的预先指针
ListNode pre = new ListNode(0);
//当前位置
ListNode cur = pre;
//进位默认取0
int carry = 0;
while(l1 != null || l2 != null) {
int x = l1 == null ? 0 : l1.val;
int y = l2 == null ? 0 : l2.val;
int sum = x + y + carry;
//进位为1,不进位为0
carry = sum / 10;
//求出当前位上的数
sum = sum % 10;
//将当前数放在链表上
cur.next = new ListNode(sum);
//当前位置后移一位
cur = cur.next;
//不等于null时才能继续向前移动
if(l1 != null)
l1 = l1.next;
if(l2 != null)
l2 = l2.next;
}
//这一步千万别忘了,当最后一次求和要进位不要遗漏
if(carry == 1) {
cur.next = new ListNode(carry);
}
//返回预先指针的下一个节点即为所求
return pre.next;
}
}
19. 删除链表的倒数第N个节点
给定一个链表,删除链表的倒数第 n 个节点,并且返回链表的头结点。
示例:
给定一个链表: 1->2->3->4->5, 和 n = 2.
当删除了倒数第二个节点后,链表变为 1->2->3->5.
class Solution {
public ListNode removeNthFromEnd(ListNode head, int n) {
//神奇的预先指针
ListNode pre = new ListNode(0);
//指向头节点
pre.next = head;
//定义两个指针
ListNode start = pre;
ListNode end = pre;
//先让start指针移动n次,以示意为例,应移动到2
//此时end指针和start指针相隔两个节点
while(n != 0){
start = start.next;
n--;
}
//让start移动到最后
//那么end则会移动到3节点的位置
//end的下一个节点即为要删除的节点
while(start.next != null){
start = start.next;
end = end.next;
}
//让end的下一个节点为下下个节点,即可删除
end.next = end.next.next;
return pre.next;
}
}
61. 旋转链表
给定一个链表,旋转链表,将链表每个节点向右移动 k 个位置,其中 k 是非负数。
示例1:
输入: 1->2->3->4->5->NULL, k = 2
输出: 4->5->1->2->3->NULL
解释:
向右旋转 1 步: 5->1->2->3->4->NULL
向右旋转 2 步: 4->5->1->2->3->NULL
示例2:
输入: 0->1->2->NULL, k = 4
输出: 2->0->1->NULL
解释:
向右旋转 1 步: 2->0->1->NULL
向右旋转 2 步: 1->2->0->NULL
向右旋转 3 步: 0->1->2->NULL
向右旋转 4 步: 2->0->1->NULL
class Solution {
public ListNode rotateRight(ListNode head, int k) {
//先判空
if(head == null) return null;
if(head.next == null) return head;
//先找到旧的尾巴,并让头尾相连
ListNode old_tail = head;
int n = 1;//用n表示链表长度
while(old_tail.next != null){
old_tail = old_tail.next;
n++;
}
old_tail.next = head;//头尾相连
//找到新的尾巴
ListNode new_tail = head;
//解释一下这里为什么k%n,在k<n的时候,新尾巴的位置为n-k-1
//当k>n的时候需要进行k%n运算,去掉整圈数
for(int i = 0;i < n - k % n - 1;i++){
new_tail = new_tail.next;
}
//新的头为新的尾巴的下一位
ListNode new_head = new_tail.next;
//新的尾巴的下一位要为null才能成为尾巴
new_tail.next = null;
return new_head;
}
}
138. 复制带随机指针的链表
给定一个链表,每个节点包含一个额外增加的随机指针,该指针可以指向链表中的任何节点或空节点。
要求返回这个链表的 深拷贝。
我们用一个由 n 个节点组成的链表来表示输入/输出中的链表。每个节点用一个 [val, random_index] 表示:
- val:一个表示 Node.val 的整数。
- random_index:随机指针指向的节点索引(范围从 0 到 n-1);如果不指向任何节点,则为 null 。
示例 1:
输入:head = [[7,null],[13,0],[11,4],[10,2],[1,0]]
输出:[[7,null],[13,0],[11,4],[10,2],[1,0]]
class Solution {
//创建一个HashMap,将访问过的节点放进去
//泛型两个Node,左侧Node为head链表,右侧为深拷贝的链表
HashMap<Node,Node> visitedHash = new HashMap<Node,Node>();
public Node copyRandomList(Node head) {
//先判空
if(head == null){
return null;
}
//如果这个节点存在HaspMap中,直接返回这个节点
if(this.visitedHash.containsKey(head)){
return this.visitedHash.get(head);
}
//如果没有这个节点,则创建一个新的节点
Node node = new Node(head.val);
//存入HashMap中
visitedHash.put(head,node);
//递归算法
node.next = copyRandomList(head.next);
node.random = copyRandomList(head.random);
return node;
}
}
206. 反转链表
反转一个链表。
实例:
输入: 1->2->3->4->5->NULL
输出: 5->4->3->2->1->NULL
class Solution {
public ListNode reverseList(ListNode head) {
ListNode cur = head;
ListNode pre = new ListNode(0);
ListNode tem = null;
while(cur != null){
tem = cur.next;
cur.next = pre.next;
pre.next = cur;
cur = tem;
}
return pre.next;
}
}