LeetCode专题----LinkedList

2. Add Two Numbers

You are given two linked lists representing two non-negative numbers. The digits are stored in reverse order and each of their nodes contain a single digit. Add the two numbers and return it as a linked list.

Input: (2 -> 4 -> 3) + (5 -> 6 -> 4)
Output: 7 -> 0 -> 8
思路:直接两个指针遍历相加,只是要注意进位,特别是最后有可能有一个进位。要保持一个头结点的引用,否则无法返回结果。

/**
 * Definition for singly-linked list.
 * public class ListNode {
 *     int val;
 *     ListNode next;
 *     ListNode(int x) { val = x; }
 * }
 */
public class Solution {
    public ListNode addTwoNumbers(ListNode l1, ListNode l2) {
        if(l1 == null || l2 == null) return null;

        ListNode p1 = l1, p2 = l2;
        ListNode fakeHead = new ListNode(0);
        ListNode node = fakeHead;
        int carry = 0;
        int sum = 0;
        while(p1 != null || p2 != null) {
            if(p1 != null) {
                sum += p1.val;
                p1 = p1.next;
            }
            if(p2 != null) {
                sum += p2.val;
                p2 = p2.next;
            }
            sum += carry;
            carry = sum / 10;
            node.next = new ListNode(sum % 10);
            node = node.next;
            sum = 0;
        }
        if(carry != 0) {
            node.next = new ListNode(carry);
        }
        return fakeHead.next;
    }
}

445. Add Two Numbers II

You are given two linked lists representing two non-negative numbers. The most significant digit comes first and each of their nodes contain a single digit. Add the two numbers and return it as a linked list.

You may assume the two numbers do not contain any leading zero, except the number 0 itself.

Follow up:
What if you cannot modify the input lists? In other words, reversing the lists is not allowed.

Example:

Input: (7 -> 2 -> 4 -> 3) + (5 -> 6 -> 4)
Output: 7 -> 8 -> 0 -> 7
思路:和上一题类似,但是需要把链表反向,下面的做法是用栈的先入后出特性来模拟反向。要注意的最后返回的链表要高位在头部。

/**
 * Definition for singly-linked list.
 * public class ListNode {
 *     int val;
 *     ListNode next;
 *     ListNode(int x) { val = x; }
 * }
 */
public class Solution {
    public ListNode addTwoNumbers(ListNode l1, ListNode l2) {
        if(l1 == null || l2 == null) return null;

        Stack<Integer> s1 = new Stack<>();
        Stack<Integer> s2 = new Stack<>();

        while(l1 != null) {
            s1.push(l1.val);
            l1 = l1.next;
        }
        while(l2 != null) {
            s2.push(l2.val);
            l2 = l2.next;
        }

        int sum = 0;
        int carry = 0;
        ListNode node = new ListNode(0);
        while(!s1.empty() || !s2.empty()) {
            if(!s1.empty()) {
                sum += s1.pop();
            }
            if(!s2.empty()) {
                sum += s2.pop();
            }
            sum += carry;
            carry = sum / 10;
            // 这一步把进位直接放在了上一个节点的值中
            ListNode head = new ListNode(carry);
            node.val = sum % 10;
            head.next = node;
            node = head;
            sum = 0;
        }
        return node.val == 0 ? node.next : node;
    }
}

19. Remove Nth Node From End of List

Given a linked list, remove the nth node from the end of list and return its head.

For example,

Given linked list: 1->2->3->4->5, and n = 2.

After removing the second node from the end, the linked list becomes 1->2->3->5.
Note:
Given n will always be valid.
Try to do this in one pass.
思路:快慢指针,快的指针先走n步。

/**
 * Definition for singly-linked list.
 * public class ListNode {
 *     int val;
 *     ListNode next;
 *     ListNode(int x) { val = x; }
 * }
 */
public class Solution {
    public ListNode removeNthFromEnd(ListNode head, int n) {
        if(head == null) {
            return null;
        }

        ListNode p = head;
        ListNode q = head;

        for(int i=0;i<n;i++) {
            q = q.next;
        }

        if(q == null) {
            head = head.next;
            return head;
        }

        while(q.next != null) {
            p = p.next;
            q = q.next;
        }
        p.next = p.next.next;
        return head;
    }
}

21. Merge Two Sorted Lists

Merge two sorted linked lists and return it as a new list. The new list should be made by splicing together the nodes of the first two lists.

/**
 * Definition for singly-linked list.
 * public class ListNode {
 *     int val;
 *     ListNode next;
 *     ListNode(int x) { val = x; }
 * }
 */
public class Solution {
    public ListNode mergeTwoLists(ListNode l1, ListNode l2) {
        if(l1 == null) return l2;
        if(l2 == null) return l1;

        ListNode fakeHead = new ListNode(0);
        ListNode node = fakeHead;
        while(l1 != null && l2 != null) {
            if(l1.val <= l2.val) {
                node.next = l1;
                l1 = l1.next;
            }
            else {
                node.next = l2;
                l2 = l2.next;
            }
            node = node.next;
        }

        if(l1 != null) {
            node.next = l1;
        }
        if(l2 != null) {
            node.next = l2;
        }
        return fakeHead.next;
    }
}

23. Merge k Sorted Lists

Merge k sorted linked lists and return it as one sorted list. Analyze and describe its complexity.
思路1:若链表时升序排列的,则用大小为k的小顶堆,这样可以保证每次O(1)的时间取出堆顶元素,然后删除堆顶元素后调整堆序的时间是O(logk)。总的时间复杂度是O(N*logk),N为k个链表总的节点数。

/**
 * Definition for singly-linked list.
 * public class ListNode {
 *     int val;
 *     ListNode next;
 *     ListNode(int x) { val = x; }
 * }
 */
public class Solution {
    public ListNode mergeKLists(ListNode[] lists) {
        if(lists == null || lists.length == 0) return null;

        PriorityQueue<ListNode> pq = new PriorityQueue<>(lists.length, new Comparator<ListNode>() {
            public int compare(ListNode a, ListNode b) {
                if(a.val > b.val) return 1;
                else if(a.val < b.val) return -1;
                else return 0;
            }
        });

        ListNode fakeHead = new ListNode(0);
        ListNode pre = fakeHead;

        for(ListNode node : lists) {
            if(node != null)
                pq.offer(node);
        }

        while(!pq.isEmpty()) {
            ListNode cur = pq.poll();
            if(cur.next != null) {
                pq.offer(cur.next);
            }
            pre.next = cur;
            pre = cur;
        }
        return fakeHead.next;
    }
}

思路2:分治。两两合并。

public class Solution {
    public ListNode mergeTwoLists(ListNode l1, ListNode l2) {
        if (l1 == null) return l2;
        if (l2 == null) return l1;

        ListNode head=null;
        ListNode former=null;
        while (l1!=null&&l2!=null) {
            if (l1.val>l2.val) {
                if (former==null) former=l2; else former.next=l2;
                if (head==null) head=former; else former=former.next;
                l2=l2.next;
            } else {
                if (former==null) former=l1; else former.next=l1;
                if (head==null) head=former; else former=former.next;
                l1=l1.next;
            }
        }
        if (l2!=null) l1=l2;
        former.next=l1;
        return head;

    }

    public ListNode mergeKLists(List<ListNode> lists) {
        if (lists.size()==0) return null;
        if (lists.size()==1) return lists.get(0);
        if (lists.size()==2) return mergeTwoLists(lists.get(0), lists.get(1));
        return mergeTwoLists(mergeKLists(lists.subList(0, lists.size()/2)), 
            mergeKLists(lists.subList(lists.size()/2, lists.size())));
    }
}

83. Remove Duplicates from Sorted List

Given a sorted linked list, delete all duplicates such that each element appear only once.

For example,
Given 1->1->2, return 1->2.
Given 1->1->2->3->3, return 1->2->3.
思路:一个一个地删,如果当前节点和下一个节点值相同,就删除下一个节点。

public class Solution {
    public ListNode deleteDuplicates(ListNode head) {
        ListNode list = head;

         while(list != null) {
             if (list.next == null) {
                 break;
             }
             if (list.val == list.next.val) {
                 list.next = list.next.next;
             } else {
                 list = list.next;
             }
         }

         return head;
    }
}

82. Remove Duplicates from Sorted List II

Given a sorted linked list, delete all nodes that have duplicate numbers, leaving only distinct numbers from the original list.

For example,
Given 1->2->3->3->4->4->5, return 1->2->5.
Given 1->1->1->2->3, return 2->3.
思路分析:关键对重复的节点不能一个一个删除,而是找到重复的最后一个节点一起删除,注释的那句话是关键。

/**
 * Definition for singly-linked list.
 * public class ListNode {
 *     int val;
 *     ListNode next;
 *     ListNode(int x) { val = x; }
 * }
 */
public class Solution {
    public ListNode deleteDuplicates(ListNode head) {
        if(head == null) return null;

        ListNode fakeHead = new ListNode(0);
        fakeHead.next = head;
        ListNode pre = fakeHead, cur = head;
        while(cur != null) {
            while(cur.next != null && cur.next.val == cur.val) {
                cur = cur.next;
            }
            //该条件成立说明pre的下一个数不重复,应保留
            if(pre.next == cur) {
                pre = pre.next;
            }
            else {
                pre.next = cur.next;
            }
            cur = cur.next;
        }
        return fakeHead.next;
    }
}

206. Reverse Linked List

Reverse a singly linked list.
解法1:循环。

/**
 * Definition for singly-linked list.
 * public class ListNode {
 *     int val;
 *     ListNode next;
 *     ListNode(int x) { val = x; }
 * }
 */
public class Solution {
    public ListNode reverseList(ListNode head) {
        if(head == null) return null;

        ListNode pre = null, nxt, cur = head;
        while(cur != null) {
            nxt = cur.next;
            cur.next = pre;
            pre = cur;
            cur = nxt;
        }
        return pre;
    }
}

解法2:递归。

public ListNode reverseList(ListNode head) {
    /* recursive solution */
    return reverseListInt(head, null);
}

private ListNode reverseListInt(ListNode head, ListNode newHead) {
    if (head == null)
        return newHead;
    ListNode next = head.next;
    head.next = newHead;
    return reverseListInt(next, head);
}

92. Reverse Linked List II

Reverse a linked list from position m to n. Do it in-place and in one-pass.

For example:
Given 1->2->3->4->5->NULL, m = 2 and n = 4,

return 1->4->3->2->5->NULL.

Note:
Given m, n satisfy the following condition:
1 ≤ m ≤ n ≤ length of list.
思路:

/**
 * Definition for singly-linked list.
 * public class ListNode {
 *     int val;
 *     ListNode next;
 *     ListNode(int x) { val = x; }
 * }
 */
public class Solution {
    public ListNode reverseBetween(ListNode head, int m, int n) {
        if(head == null) return null;

        ListNode start = null, end = null, preStart = null, nextEnd = null, fakeHead = new ListNode(0);
        fakeHead.next = head;
        ListNode node = fakeHead;
        int index = 1;
        while(node != null && node.next != null) {
            if(index == m) {
                preStart = node;
                start = node.next;
            }
            if(index == n) {
                end = node.next;
                nextEnd = node.next.next;
            }
            node = node.next;
            index++;
        }
        ListNode pre = nextEnd, cur = start, next;
        while(cur != nextEnd) {
            next = cur.next;
            cur.next = pre;
            pre = cur;
            cur = next;
        }
        preStart.next = end;
        return fakeHead.next;
    }
}

141. Linked List Cycle

Given a linked list, determine if it has a cycle in it.

Follow up:
Can you solve it without using extra space?
思路:快慢指针,若有环,二者必定会相遇。

/**
 * Definition for singly-linked list.
 * class ListNode {
 *     int val;
 *     ListNode next;
 *     ListNode(int x) {
 *         val = x;
 *         next = null;
 *     }
 * }
 */
public class Solution {
    public boolean hasCycle(ListNode head) {
        if(head == null) return false;

        ListNode slow = head, fast = head;
        while(fast != null && fast.next != null) {
            slow = slow.next;
            fast = fast.next.next;
            if(slow == fast) return true;
        }
        return false;
    }
}

142. Linked List Cycle II

Given a linked list, return the node where the cycle begins. If there is no cycle, return null.

Note: Do not modify the linked list.

Follow up:
Can you solve it without using extra space?
思路:Step 1: Determine whether there is a cycle

1.1) Using a slow pointer that move forward 1 step each time

1.2) Using a fast pointer that move forward 2 steps each time

1.3) If the slow pointer and fast pointer both point to the same location after several moving steps, there is a cycle;

1.4) Otherwise, if (fast->next == NULL || fast->next->next == NULL), there has no cycle.

Step 2: If there is a cycle, return the entry location of the cycle

2.1) L1 is defined as the distance between the head point and entry point

2.2) L2 is defined as the distance between the entry point and the meeting point

2.3) C is defined as the length of the cycle

2.4) n is defined as the travel times of the fast pointer around the cycle When the first encounter of the slow pointer and the fast pointer

According to the definition of L1, L2 and C, we can obtain:

the total distance of the slow pointer traveled when encounter is L1 + L2

the total distance of the fast pointer traveled when encounter is L1 + L2 + n * C

Because the total distance the fast pointer traveled is twice as the slow pointer, Thus:

2 * (L1+L2) = L1 + L2 + n * C => L1 + L2 = n * C => L1 = (n - 1) C + (C - L2)*

It can be concluded that the distance between the head location and entry location is equal to the distance between the meeting location and the entry location along the direction of forward movement.

So, when the slow pointer and the fast pointer encounter in the cycle, we can define a pointer “entry” that point to the head, this “entry” pointer moves one step each time so as the slow pointer. When this “entry” pointer and the slow pointer both point to the same location, this location is the node where the cycle begins.

/**
 * Definition for singly-linked list.
 * class ListNode {
 *     int val;
 *     ListNode next;
 *     ListNode(int x) {
 *         val = x;
 *         next = null;
 *     }
 * }
 */
public class Solution {
    public ListNode detectCycle(ListNode head) {
        if(head == null) return null;

        ListNode slow = head, fast = head;
        while(fast != null && fast.next != null) {
            slow = slow.next;
            fast = fast.next.next;
            if(slow == fast) {
                ListNode slow2 = head;
                while(slow != slow2) {
                    slow = slow.next;
                    slow2 = slow2.next;
                }
                return slow;
            }
        }

        return null;
    }
}

147. Insertion Sort List

Sort a linked list using insertion sort.
思路:一开始把插入排序和冒泡排序搞混了。。。囧。插入排序是保证前面一些位置是排序状态。

/**
 * Definition for singly-linked list.
 * public class ListNode {
 *     int val;
 *     ListNode next;
 *     ListNode(int x) { val = x; }
 * }
 */
public class Solution {
    public ListNode insertionSortList(ListNode head) {
        if(head == null) return null;

        ListNode fakeHead = new ListNode(0);
        ListNode pre = fakeHead; // 要被插入的位置
        ListNode cur = head; // 要被插入的节点
        ListNode next; // 下一个要被插入的节点

        while(cur != null) {
            next = cur.next;
            while(pre.next != null && pre.next.val < cur.val) {
                pre = pre.next;
            }
            cur.next = pre.next;
            pre.next = cur;
            pre = fakeHead;
            cur = next;
        }
        return fakeHead.next;
    }
}

148. Sort List

Sort a linked list in O(n log n) time using constant space complexity.
思路:归并排序。找链表中间,分隔成两个,再归并。

/**
 * Definition for singly-linked list.
 * public class ListNode {
 *     int val;
 *     ListNode next;
 *     ListNode(int x) { val = x; }
 * }
 */
public class Solution {
    public ListNode sortList(ListNode head) {
        // 第一个条件是为了防止直接输入就是null,第二个条件是递归终止条件
        if(head == null || head.next == null) return head;

        ListNode head1 = head, slow = head, fast = head, preSlow = null;
        while(fast != null && fast.next != null) {
            preSlow = slow;
            slow = slow.next;
            fast = fast.next.next;
        }

        ListNode head2 = slow;
        preSlow.next = null;
        // 要避免两个都是null的情况发生
        return merge(sortList(head1), sortList(head2));
    }

    private ListNode merge(ListNode head1, ListNode head2) {
        if(head1 == null) return head2;
        if(head2 == null) return head1;

        ListNode fakeHead = new ListNode(0);
        ListNode node = fakeHead;
        while(head1 != null && head2 != null) {
            if(head1.val <= head2.val) {
                node.next = head1;
                head1 = head1.next;
            } else {
                node.next = head2;
                head2 = head2.next;
            }
            node = node.next;
        }
        if(head1 != null) {
            node.next = head1;
        }
        if(head2 != null) {
            node.next = head2;
        }
        return fakeHead.next;
    }
}

160. Intersection of Two Linked Lists

Write a program to find the node at which the intersection of two singly linked lists begins.

For example, the following two linked lists:

A: a1 → a2

c1 → c2 → c3

B: b1 → b2 → b3
begin to intersect at node c1.

Notes:

If the two linked lists have no intersection at all, return null.
The linked lists must retain their original structure after the function returns.
You may assume there are no cycles anywhere in the entire linked structure.
Your code should preferably run in O(n) time and use only O(1) memory.

/**
 * Definition for singly-linked list.
 * public class ListNode {
 *     int val;
 *     ListNode next;
 *     ListNode(int x) {
 *         val = x;
 *         next = null;
 *     }
 * }
 */
public class Solution {
    public ListNode getIntersectionNode(ListNode headA, ListNode headB) {
        if(headA == null || headB == null) return null;
        // 获取长度
        int lenA = getListLen(headA), lenB = getListLen(headB);
        // 分别获取长短链表头节点以及他们的差,这种写法减少代码重复
        ListNode listHeadLong = headA, listHeadShort = headB;
        int lenDiff = lenA - lenB;
        if(lenB > lenA) {
            listHeadLong = headB;
            listHeadShort = headA;
            lenDiff = lenB - lenA;
        }
        // 长链表先走齐
        while(lenDiff != 0) {
            listHeadLong = listHeadLong.next;
            lenDiff--;
        }
        // 齐头并进,寻找第一个交点
        while(listHeadLong != null && listHeadShort != null && listHeadLong != listHeadShort) {
            listHeadLong = listHeadLong.next;
            listHeadShort = listHeadShort.next;
        }
        return listHeadLong;
    }
    private int getListLen(ListNode head) {
        ListNode node = head;
        int len = 0;
        while(node != null) {
            len++;
            node = node.next;
        }
        return len;
    }
}

203. Remove Linked List Elements

Remove all elements from a linked list of integers that have value val.
思路:此题很直接。链表的题最好是建一个假想的头结点,这样就不用特殊考虑头结点了。

public class Solution {
    public ListNode removeElements(ListNode head, int val) {
        ListNode fakeHead = new ListNode(-1);
        fakeHead.next = head;
        ListNode curr = head, prev = fakeHead;
        while (curr != null) {
            if (curr.val == val) {
                prev.next = curr.next;
            } else {
                prev = prev.next;
            }
            curr = curr.next;
        }
        return fakeHead.next;
    }
}

234. Palindrome Linked List

Given a singly linked list, determine if it is a palindrome.
分析:本题涉及到链表中间节点的寻找和链表的反向。在寻找中间节点时,要把判断快指针的情况作为终止条件,在比较两个链表时要把短的链表的情况作为终止条件。

/**
 * Definition for singly-linked list.
 * public class ListNode {
 *     int val;
 *     ListNode next;
 *     ListNode(int x) { val = x; }
 * }
 */
public class Solution {
    public boolean isPalindrome(ListNode head) {
        if(head==null || head.next==null)
            return true;

        ListNode middle = partition(head);
        middle = reverse(middle);

        while(middle != null) {
            if(head.val != middle.val) {
                return false;
            }
            head = head.next;
            middle = middle.next;
        }
        return true;
    }

    private ListNode partition(ListNode head) {
        ListNode p = head;
        while(p.next != null && p.next.next != null) {
            head = head.next;
            p = p.next.next;
        }

        p = head.next;
        head.next = null;
        return p;
    }

    private ListNode reverse(ListNode head) {
        if(head == null || head.next == null)
            return head;

        ListNode pre = head;
        ListNode cur = head.next;
        head.next = null;

        ListNode nxt = null;

        while(cur != null) {
            nxt = cur.next;
            cur.next = pre;
            pre = cur;
            cur = nxt;
        }

        return pre;
    }
}

237. Delete Node in a Linked List

Write a function to delete a node (except the tail) in a singly linked list, given only access to that node.

Supposed the linked list is 1 -> 2 -> 3 -> 4 and you are given the third node with value 3, the linked list should become 1 -> 2 -> 4 after calling your function.
思路:由于只给了当前要删除的节点,所以只能把后面节点的值前移一个,然后删除最后的节点。

/**
 * Definition for singly-linked list.
 * public class ListNode {
 *     int val;
 *     ListNode next;
 *     ListNode(int x) { val = x; }
 * }
 */
public class Solution {
    public void deleteNode(ListNode node) {
        if(node == null)
            return;
        ListNode nxt = node.next;
        while(true) {
            if(nxt == null) {
                node = null;
                break;
            }
            node.val = nxt.val;
            node = nxt;
            nxt = nxt.next;
        }
    }
}

328. Odd Even Linked List

Given a singly linked list, group all odd nodes together followed by the even nodes. Please note here we are talking about the node number and not the value in the nodes.

You should try to do it in place. The program should run in O(1) space complexity and O(nodes) time complexity.

Example:
Given 1->2->3->4->5->NULL,
return 1->3->5->2->4->NULL.

Note:
The relative order inside both the even and odd groups should remain as it was in the input.
The first node is considered odd, the second node even and so on …
思路:多指针。 奇节点的下一个就是下一个偶节点的下一个,偶节点的下一个就是下一个奇节点的下一个。

/**
 * Definition for singly-linked list.
 * public class ListNode {
 *     int val;
 *     ListNode next;
 *     ListNode(int x) { val = x; }
 * }
 */
public class Solution {
    public ListNode oddEvenList(ListNode head) {
        if(head == null) return null;

        ListNode odd = head, even = odd.next, evenHead = even;
        while(even != null && even.next != null) {
            odd.next = even.next;
            odd = odd.next;
            even.next = odd.next;
            even = even.next;
        }
        odd.next = evenHead;
        return head;
    }
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值