美文网首页互联网入门指南
leetcode高频题——链表

leetcode高频题——链表

作者: 进击的李同学 | 来源:发表于2020-02-27 15:57 被阅读0次
    掘金.png

    概述

    本文是从leetcode题库中精选出的关于链表的题目,在面试中具有较高的出现频率。

    160. 相交链表

    编写一个程序,找到两个单链表相交的起始节点。
    如下面的两个链表:

    image
    在节点 c1 开始相交。
    示例 1:
    image
    输入:intersectVal = 8, listA = [4,1,8,4,5], listB = [5,0,1,8,4,5], skipA = 2, skipB = 3
    输出:Reference of the node with value = 8
    输入解释:相交节点的值为 8 (注意,如果两个列表相交则不能为 0)。从各自的表头开始算起,链表 A 为 [4,1,8,4,5],链表 B 为 [5,0,1,8,4,5]。在 A 中,相交节点前有 2 个节点;在 B 中,相交节点前有 3 个节点。
    示例 2:
    image
    输入:intersectVal = 2, listA = [0,9,1,2,4], listB = [3,2,4], skipA = 3, skipB = 1
    输出:Reference of the node with value = 2
    输入解释:相交节点的值为 2 (注意,如果两个列表相交则不能为 0)。从各自的表头开始算起,链表 A 为 [0,9,1,2,4],链表 B 为 [3,2,4]。在 A 中,相交节点前有 3 个节点;在 B 中,相交节点前有 1 个节点。
    示例 3:
    image
    输入:intersectVal = 0, listA = [2,6,4], listB = [1,5], skipA = 3, skipB = 2
    输出:null
    输入解释:从各自的表头开始算起,链表 A 为 [2,6,4],链表 B 为 [1,5]。由于这两个链表不相交,所以 intersectVal 必须为 0,而 skipA 和 skipB 可以是任意值。
    解释:这两个链表不相交,因此返回 null。
    注意:
    如果两个链表没有交点,返回 null.
    在返回结果后,两个链表仍须保持原有的结构。
    可假定整个链表结构中没有循环。
    程序尽量满足 O(n) 时间复杂度,且仅用 O(1) 内存。
    public class Solution {
        public ListNode getIntersectionNode(ListNode headA, ListNode headB) {
            if (headA == null || headB == null) {
                return null;
            }
            ListNode curA = headA;
            ListNode curB = headB;
            while (curA != curB) {
                curA = curA == null ? headB : curA.next;
                curB = curB == null ? headA : curB.next;
            }
            return curA;
        }
    }
    

    206. 反转链表

    反转一个单链表。
    示例:
    输入: 1->2->3->4->5->NULL
    输出: 5->4->3->2->1->NULL
    进阶:
    你可以迭代或递归地反转链表。你能否用两种方法解决这道题?

    class Solution {
        public ListNode reverseList(ListNode head) {
            ListNode newHead = null;
            while (head != null){
                ListNode next = head.next;
                head.next = newHead;
                newHead = head;
                head = next;
            }
            return newHead;
        }
    }
    

    21. 合并两个有序链表

    将两个有序链表合并为一个新的有序链表并返回。新链表是通过拼接给定的两个链表的所有节点组成的。
    示例:
    输入:1->2->4, 1->3->4
    输出:1->1->2->3->4->4

    public class Solution {
        public ListNode mergeTwoLists(ListNode l1, ListNode l2) {
            if (l1 == null) {
                return l2;
            }else if (l2 == null) {
                return l1;
            } else if (l1.val > l2.val) {
                l2.next = mergeTwoLists(l1, l2.next);
                return l2;
            } else{
                l1.next = mergeTwoLists(l1.next, l2);
                return l1;
            }
        }
    }
    

    83. 删除排序链表中的重复元素

    给定一个排序链表,删除所有重复的元素,使得每个元素只出现一次。
    示例 1:
    输入: 1->1->2
    输出: 1->2
    示例 2:
    输入: 1->1->2->3->3
    输出: 1->2->3

    class Solution {
        public ListNode deleteDuplicates(ListNode head) {
            ListNode cur = head;
            while(cur != null && cur.next != null){
                if(cur.next.val == cur.val){
                    cur.next = cur.next.next;
                }else{
                    cur = cur.next;
                }
            }
            return head;
        }
    }
    

    19. 删除链表的倒数第N个节点

    给定一个链表,删除链表的倒数第 n 个节点,并且返回链表的头结点。
    示例:
    给定一个链表: 1->2->3->4->5, 和 n = 2.
    当删除了倒数第二个节点后,链表变为 1->2->3->5.
    说明:
    给定的 n 保证是有效的。
    进阶:
    你能尝试使用一趟扫描实现吗?

    class Solution {
        public ListNode removeNthFromEnd(ListNode head, int n) {
            ListNode slow = head;
            ListNode fast = head;
            while(n > 0 && fast != null){
                fast = fast.next;
                n--;
            }
            if(fast == null){
                return n == 0 ? head.next:head;
            }
            while(fast.next != null){
                fast = fast.next;
                slow = slow.next;
            }
            slow.next = slow.next.next;
            return head;
        }
    }
    

    24. 两两交换链表中的节点

    给定一个链表,两两交换其中相邻的节点,并返回交换后的链表。
    你不能只是单纯的改变节点内部的值,而是需要实际的进行节点交换。
    示例:
    给定 1->2->3->4, 你应该返回 2->1->4->3.

    class Solution {
        public ListNode swapPairs(ListNode head) {
           if(head == null || head.next == null){
               return head;
           }
           ListNode firstNode = head;
           ListNode secondNode = head.next;
           firstNode.next = swapPairs(secondNode.next);
           secondNode.next = firstNode;
           return secondNode;
        }
    }
    

    445. 两数相加 II

    给定两个非空链表来代表两个非负整数。数字最高位位于链表开始位置。它们的每个节点只存储单个数字。将这两数相加会返回一个新的链表。
    你可以假设除了数字 0 之外,这两个数字都不会以零开头。
    进阶:
    如果输入链表不能修改该如何处理?换句话说,你不能对列表中的节点进行翻转。
    示例:
    输入: (7 -> 2 -> 4 -> 3) + (5 -> 6 -> 4)
    输出: 7 -> 8 -> 0 -> 7

    class Solution {
        public ListNode addTwoNumbers(ListNode l1, ListNode l2) {
            LinkedList<Integer> stackA = buildStack(l1);
            LinkedList<Integer> stackB = buildStack(l2);
            int carry = 0;
            ListNode head = new ListNode(-1);
            while (!stackA.isEmpty() || !stackB.isEmpty() || carry != 0) {
                int x = stackA.isEmpty() ? 0 : stackA.pop();
                int y = stackB.isEmpty() ? 0 : stackB.pop();
                int sum = x + y + carry;
                ListNode node = new ListNode(sum % 10);
                node.next = head.next;
                head.next = node;
                carry = sum / 10;
            }
            return head.next;
        }
    
        private LinkedList<Integer> buildStack(ListNode head) {
            LinkedList<Integer> stack = new LinkedList<>();
            while (head != null) {
                stack.push(head.val);
                head = head.next;
            }
            return stack;
        }
    }
    

    234. 回文链表

    请判断一个链表是否为回文链表。
    示例 1:
    输入: 1->2
    输出: false
    示例 2:
    输入: 1->2->2->1
    输出: true
    进阶:
    你能否用 O(n) 时间复杂度和 O(1) 空间复杂度解决此题?

    class Solution {
        public boolean isPalindrome(ListNode head) {
            if (head == null || head.next == null){
                return true;
            }
            ListNode slow = head, fast = head.next;
            while (fast != null && fast.next != null) {
                slow = slow.next;
                fast = fast.next.next;
            }
            if (fast != null){
                slow = slow.next;
            }
            cut(head, slow);
            return isEqual(head, reverse(slow));
        }
    
        private void cut(ListNode head, ListNode cutNode) {
            while (head.next != cutNode) {
                head = head.next;
            }
            head.next = null;
        }
    
        private ListNode reverse(ListNode head) {
            ListNode newHead = null;
            while (head != null) {
                ListNode nextNode = head.next;
                head.next = newHead;
                newHead = head;
                head = nextNode;
            }
            return newHead;
        }
    
        private boolean isEqual(ListNode l1, ListNode l2) {
            while (l1 != null && l2 != null) {
                if (l1.val != l2.val){
                    return false;
                }
                l1 = l1.next;
                l2 = l2.next;
            }
            return true;
        }
    }
    

    725. 分隔链表

    给定一个头结点为 root 的链表, 编写一个函数以将链表分隔为 k 个连续的部分。
    每部分的长度应该尽可能的相等: 任意两部分的长度差距不能超过 1,也就是说可能有些部分为 null。
    这k个部分应该按照在链表中出现的顺序进行输出,并且排在前面的部分的长度应该大于或等于后面的长度。
    返回一个符合上述规则的链表的列表。
    举例: 1->2->3->4, k = 5 // 5 结果 [ [1], [2], [3], [4], null ]
    示例 1:
    输入:
    root = [1, 2, 3], k = 5
    输出: [[1],[2],[3],[],[]]
    解释:
    输入输出各部分都应该是链表,而不是数组。
    例如, 输入的结点 root 的 val= 1, root.next.val = 2, \root.next.next.val = 3, 且 root.next.next.next = null。
    第一个输出 output[0] 是 output[0].val = 1, output[0].next = null。
    最后一个元素 output[4] 为 null, 它代表了最后一个部分为空链表。
    示例 2:
    输入:
    root = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10], k = 3
    输出: [[1, 2, 3, 4], [5, 6, 7], [8, 9, 10]]
    解释:
    输入被分成了几个连续的部分,并且每部分的长度相差不超过1.前面部分的长度大于等于后面部分的长度。
    提示:
    root 的长度范围: [0, 1000].
    输入的每个节点的大小范围:[0, 999].
    k 的取值范围: [1, 50].

    class Solution {
        public ListNode[] splitListToParts(ListNode root, int k) {
            ListNode cur = root;
            int length = 0;
            while(cur != null){
                cur = cur.next;
                length++;
            }
            int width = length / k;
            // 前几个子链表需要长度加一
            int number = length % k;
            cur = root;
            ListNode[] ans = new ListNode[k];
            for(int i = 0; i<k; i++){
                ListNode head = cur;
                for(int j = 0;j< width + (i < number ? 1 : 0) - 1; j++){
                    if(cur != null){
                        cur = cur.next;
                    }
                }
                if(cur != null){
                    ListNode prev = cur;
                    cur = cur.next;
                    prev.next = null; 
                }
                ans[i] = head;
            }
            return ans;
        }
    }
    

    328. 奇偶链表

    给定一个单链表,把所有的奇数节点和偶数节点分别排在一起。请注意,这里的奇数节点和偶数节点指的是节点编号的奇偶性,而不是节点的值的奇偶性。
    请尝试使用原地算法完成。你的算法的空间复杂度应为 O(1),时间复杂度应为 O(nodes),nodes 为节点总数。
    示例 1:
    输入: 1->2->3->4->5->NULL
    输出: 1->3->5->2->4->NULL
    示例 2:
    输入: 2->1->3->5->6->4->7->NULL
    输出: 2->3->6->7->1->5->4->NULL
    说明:
    应当保持奇数节点和偶数节点的相对顺序。
    链表的第一个节点视为奇数节点,第二个节点视为偶数节点,以此类推。

    class Solution {
        public ListNode oddEvenList(ListNode head) {
            if(head == null){
                return head;
            }
            ListNode odd = head;
            ListNode even = head.next;
            ListNode 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;
        }
    }
    

    最后,期待您的订阅和点赞,同时也期待您的批评与指正!一个坚持原创的博客,致力于用简单的语言将编程这点事讲清楚,如果你想入门编程,或者是对编程感兴趣,请关注博主,每周都会更新

    相关文章

      网友评论

        本文标题:leetcode高频题——链表

        本文链接:https://www.haomeiwen.com/subject/prqxhhtx.html