今天更新的链表相关的题目~
- 中等 两数相加 Add Two Numbers
20.07.13
思路:一个carry,然后建表。
class Solution {
public ListNode addTwoNumbers(ListNode l1, ListNode l2) {
ListNode dummy = new ListNode(0);
ListNode curr = dummy;
int carry = 0;
while(l1 != null || l2 != null || carry != 0){
int val1 = l1 == null ? 0 : l1.val;
int val2 = l2 == null ? 0 : l2.val;
int sum = val1 + val2 + carry;
carry = sum / 10;
ListNode sumNode = new ListNode(sum % 10);
curr.next = sumNode;
curr = curr.next;
if(l1 != null) l1 = l1.next;
if(l2 != null) l2 = l2.next;
}
return dummy.next;
}
}
- 简单 合并两个有序链表 Merge Two Sorted Lists
20.07.13
思路:之前想的太复杂了。
class Solution {
public ListNode mergeTwoLists(ListNode l1, ListNode l2) {
ListNode dummy = new ListNode(0);
ListNode curr = dummy;
while(l1 != null && l2 != null){
if(l1.val < l2.val) {
curr.next = l1;
l1 = l1.next;
}else{
curr.next = l2;
l2 = l2.next;
}
curr = curr.next;
}
if(l1 != null){
curr.next = l1;
}else{
curr.next = l2;
}
return dummy.next;
}
}
- 困难 合并K个有序链表 Merge K Sorted Lists
20.07.14
思路:这里是重写了priorityqueue的compare方法,比较有意思。
class Solution {
public ListNode mergeKLists(ListNode[] lists) {
if(lists.length == 0) return null;
ListNode dummyHead = new ListNode(0);
ListNode curr = dummyHead;
PriorityQueue<ListNode> pq = new PriorityQueue<>(new Comparator<ListNode>(){
@Override
public int compare(ListNode o1,ListNode o2){
return o1.val - o2.val;
}
});
for(ListNode list:lists){
if(list == null) continue;
pq.add(list);
}
while(!pq.isEmpty()){
ListNode nextNode = pq.poll();
curr.next = nextNode;
curr = curr.next;
if(nextNode.next != null){
pq.add(nextNode.next);
}
}
return dummyHead.next;
}
}
- 中等 两两交换链表中的节点 Swap Nodes in Pairs
20.07.13
思路:也是递归。链表的题想不出来就想递归。
class Solution {
public ListNode swapPairs(ListNode head) {
if(head == null || head.next == null) return head;
ListNode curr = head.next;
head.next = swapPairs(curr.next);
curr.next = head;
return curr;
}
}
- 困难 K个一组翻转链表 Reverse Nodes in K Group
20.07.13
思路:这个题的难点在于翻转。这个最好记一下。next = curr.next; curr.next = next.next; next.next = prev.next; prev.next = next; 也不难记,就是一个回环。
class Solution {
public ListNode reverseKGroup(ListNode head, int k) {
ListNode dummy = new ListNode(0);
dummy.next = head;
ListNode prev = dummy;
ListNode curr = head;
ListNode next;
int length = 0;
while(head != null){
length++;
head = head.next;
}
head = dummy.next;
for(int i=0;i<length/k;i++){
for(int j=0;j<k-1;j++){
next = curr.next;
curr.next = next.next;
next.next = prev.next;
prev.next = next;
}
prev = curr;
curr = prev.next;
}
return dummy.next;
}
}
- 中等 删除排序链表中的重复元素II Remove Duplicates From Sorted List II
20.07.13
思路:为什么这个题用递归好做?因为可能多次出现的是连续的,比如111122223333,这样的话用递归好一些,如同遍历二叉树。
class Solution {
public ListNode deleteDuplicates(ListNode head) {
if(head == null || head.next == null) return head;
ListNode curr = head.next;
if(head.val == curr.val){
while(curr != null && head.val == curr.val){
curr = curr.next;
}
head = deleteDuplicates(curr);
}else{
head.next = deleteDuplicates(curr);
}
return head;
}
}
- 简单 删除排序链表中的重复元素 Remove Duplicates from Sorted List
20.07.14
思路:第一眼看成了82题,晕。
class Solution {
public ListNode deleteDuplicates(ListNode head) {
if(head == null || head.next == null) return head;
head.next = deleteDuplicates(head.next);
if(head.val == head.next.val) head = head.next;
return head;
}
}
- 中等 反转链表II Reverse Link List II
20.07.14
思路:非常简单,做过反转链表的就会写,不过是在后面一块反转罢了。
class Solution {
public ListNode reverseBetween(ListNode head, int m, int n) {
ListNode dummy = new ListNode(0);
dummy.next = head;
ListNode prev = dummy;
for(int i=1;i<m;i++){
prev = prev.next;
}
ListNode curr = prev.next;
for(int i=m;i<n;i++){
ListNode next = curr.next;
curr.next = next.next;
next.next = prev.next;
prev.next = next;//背下来
}
return dummy.next;
}
}
- 中等 复制带随机指针的链表 Copy List With Random Pointer
20.07.14
思路:用Map
class Solution {
public Node copyRandomList(Node head) {
if(head == null) return head;
Node node = head;
Map<Node,Node> map = new HashMap<>();
while(node != null){
Node clone = new Node(node.val,null,null);
map.put(node,clone);
node = node.next;
}
node = head;
while(node != null){
map.get(node).next = map.get(node.next);
map.get(node).random = map.get(node.random);
node = node.next;
}
return map.get(head);
}
}
- 中等 重排链表 Reorder List
20.07.14
思路:真TM难。
class Solution {
public void reorderList(ListNode head) {
if(head == null || head.next == null) return ;
ListNode slow = head;
ListNode fast = head;
while(fast.next != null && fast.next.next != null){
fast = fast.next.next;
slow = slow.next;
}
ListNode reverseBegin = slow.next;
slow.next = null;
reverseBegin = reverse(reverseBegin);
ListNode curr = head;
while(curr != null && reverseBegin != null){
ListNode curSecond = reverseBegin;
reverseBegin = reverseBegin.next;
ListNode nextCur = curr.next;
curSecond.next = curr.next;
curr.next = curSecond;
curr = nextCur;
}
}
public ListNode reverse(ListNode head){
ListNode p1 = null;
ListNode p2 = head;
ListNode p3 = p2;
while(p2!= null){
p3 = p2.next;
p2.next = p1;
p1 = p2;
p2 = p3;
}
return p1;
}
}
- 中等 对链表进行插入排序 Insertion Sort List
20.07.15
思路:比较前驱与现在,之后交换节点。我想画个图在这里。
class Solution {
public ListNode insertionSortList(ListNode head) {
ListNode dummy = new ListNode(0);
ListNode prev;
dummy.next = head;
while(head != null && head.next != null){
if(head.val <= head.next.val){
head = head.next;continue;
}
prev = dummy;
while(prev.next.val < head.next.val) prev = prev.next;
ListNode curr = head.next;
head.next = curr.next;
curr.next = prev.next;
prev.next = curr;
}
return dummy.next;
}
}
- 中等 排序链表 Sort List
20.07.15
思路:
class Solution {
public ListNode sortList(ListNode head) {
return merger(head);
}
private ListNode merger(ListNode head){
if(head == null || head.next == null) return head;
// 找中点
ListNode slow = head;
ListNode fast = head.next.next;
ListNode left;
ListNode right;
while(fast != null && fast.next != null){
slow = slow.next;
fast = fast.next.next;
}
//右边二分
right = merger(slow.next);
//中间断开
slow.next = null;
//左边二分
left = merger(head);
return mergeList(left,right);
}
private ListNode mergeList(ListNode left,ListNode right){
ListNode dummy = new ListNode(-1);
ListNode p = dummy;
//这里相当于重新拷贝了一个链表,left和right就是左和右两个子链表
while(left != null && right != null){
if(left.val < right.val){
p.next = left;
left = left.next;
}else{
p.next = right;
right = right.next;
}
p = p.next;
}
//一个挂没了就连上另一个
p.next = left == null ? right : left;
return dummy.next;
}
}
- 简单 相交链表 Intersection of Two Linked Lists
20.07.15
思路:这好像就是那个很浪漫的那个题,对的人会再相逢。
public class Solution {
public ListNode getIntersectionNode(ListNode headA, ListNode headB) {
if(headA == null || headB == null) return null;
ListNode p1 = headA;
ListNode p2 = headB;
while(p1 != p2){
p1 = (p1 == null) ? headB : p1.next;//到头了就走另一个链表
p2 = (p2 == null) ? headA : p2.next;
}
return p1;
}
}
- 简单 移除链表元素 Remove Linked List Elements
20.07.15
思路:非常常规的一个题。
class Solution {
public ListNode removeElements(ListNode head, int val) {
if(head == null) return head;
ListNode dummy = new ListNode(0);
ListNode curr = dummy;//一般curr要从dummy开始,尽量少从head开始
dummy.next = head;
while(curr.next != null){
if(curr.next.val == val){
curr.next = curr.next.next;//若移除,则不要在这里就curr=curr.next
}else{
curr = curr.next;
}
}
return dummy.next;
}
}
- 简单 反转链表 Reverse Linked List
20.07.15
思路:不用太复杂,这个思路其实是最清楚的。相当于三指针一个一个折回去。
class Solution {
public ListNode reverseList(ListNode head) {
ListNode prev = null;
ListNode curr = head;
while(curr != null){
ListNode next = curr.next;
curr.next = prev;//指针回来
prev = curr;
curr = next;//右移
}
return prev;
}
}
- 简单 删除链表中的元素 Delete Node in a Linked List
20.07.15
思路:这题题目讲的不太好(翻译的不清楚),不用复习了。
class Solution {
public void deleteNode(ListNode node) {
node.val = node.next.val;
node.next = node.next.next;
}
}