美文网首页
1.链表(一)

1.链表(一)

作者: 今天柚稚了么 | 来源:发表于2020-08-06 23:42 被阅读0次

    题目汇总https://leetcode-cn.com/tag/linked-list/

    2. 两数相加中等

    19. 删除链表的倒数第N个节点中等 [✔]

    21. 合并两个有序链表简单 [✔]

    23. 合并K个排序链表困难(没有做)

    24. 两两交换链表中的节点中等[✔]

    25. K 个一组翻转链表困难(没有做)

    61. 旋转链表中等

    82. 删除排序链表中的重复元素 II中等

    83. 删除排序链表中的重复元素简单[✔]

    86. 分隔链表中等[✔]

    2. 两数相加中等

    给出两个 非空 的链表用来表示两个非负的整数。其中,它们各自的位数是按照 逆序 的方式存储的,并且它们的每个节点只能存储 一位 数字。
    如果,我们将这两个数相加起来,则会返回一个新的链表来表示它们的和。
    您可以假设除了数字 0 之外,这两个数都不会以 0 开头。
    输入:(2 -> 4 -> 3) + (5 -> 6 -> 4)
    输出:7 -> 0 -> 8
    原因:342 + 465 = 807

    思路:

    见精选解题

    /**
     * Definition for singly-linked list.
     * public class ListNode {
     *     int val;
     *     ListNode next;
     *     ListNode(int x) { val = x; }
     * }
     */
    class Solution {
        public ListNode addTwoNumbers(ListNode l1, ListNode l2) {
            ListNode pre = new ListNode(0);
            ListNode cur = pre;
            int carry = 0;
            while(l1!=null || l2!=null){
                int i = (l1 != null) ? l1.val : 0;
                int j = (l2 != null) ? l2.val : 0;
                int sum = i + j + carry;
                carry = sum / 10;
                sum = sum % 10;
                cur.next = new ListNode(sum);
                cur = cur.next;
     
                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.
    说明:给定的 n 保证是有效的。
    进阶:你能尝试使用一趟扫描实现吗?

    思路一:两次遍历

    删除链表的倒数第N个结点相当于删除链表的第(L-N+1)个结点。第一次遍历得出链表的长度L,哑结点的设置非常有必要。

    /**
     * Definition for singly-linked list.
     * public class ListNode {
     *     int val;
     *     ListNode next;
     *     ListNode(int x) { val = x; }
     * }
     */
    class Solution {
        public ListNode removeNthFromEnd(ListNode head, int n) {
            ListNode dummy = new ListNode(0);
            dummy.next = head;
            ListNode first = head;
            int length = 0;
            while(first!=null){
                first = first.next;
                length++; 
            }
            length = length - n;
            first = dummy;
            while(length>0){
                first = first.next;
                length--;
                
            }
            first.next = first.next.next;
        return dummy.next;
        }
    }
    
    思路二:一次遍历

    使用两个指针,两个指针之间保持恒定的间隔,当第一个指针到达最后一个结点时,第二个指针将指向从最后一个结点数起的第 n 个结点。

    /**
     * Definition for singly-linked list.
     * public class ListNode {
     *     int val;
     *     ListNode next;
     *     ListNode(int x) { val = x; }
     * }
     */
    class Solution {
        public ListNode removeNthFromEnd(ListNode head, int n) {
            //设置哑结点
            ListNode dummy = new ListNode(0);
            dummy.next = head;
            ListNode first = head;
            ListNode second = head;
            //第一个指针先指向第(l-n+2)个结点,即要删除的结点的前一个结点
            for(int i=1;i<=n+1;i++){
                first = first.next;
            }
            //两个指针一起移动,第二个指针指向要删除的结点
            while(first!=null){
                first = first.next;
                second = second.next;
            }
            //此时删除结点
            second.next = second.next.next;
    
        return dummy.next;
        }
    }
    

    21. 合并两个有序链表简单 [✔]

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

    思路:直接归并排序
    /**
     * Definition for singly-linked list.
     * public class ListNode {
     *     int val;
     *     ListNode next;
     *     ListNode(int x) { val = x; }
     * }
     */
    class Solution {
        public ListNode mergeTwoLists(ListNode l1, ListNode l2) {
           ListNode dummy = new ListNode(-1);
           ListNode cur = dummy;
           while(l1!=null&&l2!=null){
               if(l1.val <= l2.val){
                   cur.next = l1;
                   l1 = l1.next;
               }else{
                   cur.next = l2;
                   l2 = l2.next;
               }
               cur = cur.next;
           }
           //一个链表为空
           if(l1==null){
                 cur.next = l2;
            }
            else if(l2==null){
                cur.next = l1;
            } 
        return dummy.next;
        }
    }
    
    思路二:递归

    两个链表头部较小的一个与剩下元素的 merge 操作结果合并

    /**
     * Definition for singly-linked list.
     * public class ListNode {
     *     int val;
     *     ListNode next;
     *     ListNode(int x) { val = x; }
     * }
     */
    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) {
                l1.next = mergeTwoLists(l1.next, l2);
                return l1;
            }
            else {
                l2.next = mergeTwoLists(l1, l2.next);
                return l2;
            }
    
        }
    }
    

    23. 合并K个排序链表困难

    合并 k个排序链表,返回合并后的排序链表。请分析和描述算法的复杂度。
    输入:
    [
    1->4->5,
    1->3->4,
    2->6
    ]
    输出: 1->1->2->3->4->4->5->6

    24. 两两交换链表中的节点中等[✔]

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

    思路一:非递归

    /**
     * Definition for singly-linked list.
     * public class ListNode {
     *     int val;
     *     ListNode next;
     *     ListNode(int x) { val = x; }
     * }
     */
    class Solution {
        public ListNode swapPairs(ListNode head) {
            ListNode dummy = new ListNode(-1);
            ListNode pre = dummy;
            pre.next = head;
            while(pre.next!=null&&pre.next.next!=null){
                ListNode t = pre.next.next;
                pre.next.next = t.next;
                t.next = pre.next;
                pre.next = t;
                pre = t.next;
            }
        return dummy.next;
        }
    }
    
    思路二:递归
    /**
     * Definition for singly-linked list.
     * public class ListNode {
     *     int val;
     *     ListNode next;
     *     ListNode(int x) { val = x; }
     * }
     */
    class Solution {
        public ListNode swapPairs(ListNode head) {
            if(head==null||head.next==null)
                return head;
            ListNode first = head;
            ListNode second = head.next;
            head = second;
            first.next = swapPairs(second.next);
            second.next = first;
        return head;
    
        }
    }
    
    

    25. K 个一组翻转链表困难

    给你一个链表,每 k个节点一组进行翻转,请你返回翻转后的链表。
    k是一个正整数,它的值小于或等于链表的长度。
    如果节点总数不是 k的整数倍,那么请将最后剩余的节点保持原有顺序。
    给你这个链表:1->2->3->4->5
    k= 2 时,应当返回: 2->1->4->3->5
    k= 3 时,应当返回: 3->2->1->4->5
    说明
    你的算法只能使用常数的额外空间。
    你不能只是单纯的改变节点内部的值,而是需要实际进行节点交换。

    61. 旋转链表中等

    给定一个链表,旋转链表,将链表每个节点向右移动 k个位置,其中 k是非负数。
    输入: 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

    思路:

    找到链表的表尾,表尾指向表头,将链表闭合成环,再确定新的链表头和链表尾

    /**
     * Definition for singly-linked list.
     * public class ListNode {
     *     int val;
     *     ListNode next;
     *     ListNode(int x) { val = x; }
     * }
     */
    class Solution {
        public ListNode rotateRight(ListNode head, int k) {
            if (head == null) 
                return null;
            if (head.next == null) 
                return head;
            ListNode cur = head;
            int length = 1;
            while(cur.next!=null){
                length++;
                cur = cur.next;
            }
            cur.next = head;//链表连成环
            for(int i=0;i<length-k%length;i++){
                cur = cur.next;
            }
            ListNode new_head = cur.next;//找到新的链表头
            cur.next = null;//断开
        return new_head;
    
        }
    }
    

    82. 删除排序链表中的重复元素 II中等

    给定一个排序链表,删除所有含有重复数字的节点,只保留原始链表中没有重复出现的数字。
    输入: 1->2->3->3->4->4->5
    输出: 1->2->5

    思路:

    创建一个临时指针temp

    /**
     * Definition for singly-linked list.
     * public class ListNode {
     *     int val;
     *     ListNode next;
     *     ListNode(int x) { val = x; }
     * }
     */
    class Solution {
        public ListNode deleteDuplicates(ListNode head) {
            ListNode dummy = new ListNode(-1);
            dummy.next = head;
            ListNode cur = dummy;
            while(cur.next!=null&&cur.next.next!=null){
                ListNode temp = cur.next;
                if(cur.next.val == cur.next.next.val){
                    while (temp != null && temp.next != null && temp.val == temp.next.val ) {
                        temp = temp.next;
                    }
                    cur.next = temp.next;
                } 
                else
                    cur = cur.next;
                }   
        return dummy.next;
       
        }
    }
    

    83. 删除排序链表中的重复元素简单[✔]

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

    思路:

    比较当前结点的值和它之后的结点值确定它是否为重复结点。

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

    86. 分隔链表中等[✔]

    给定一个链表和一个特定值x,对链表进行分隔,使得所有小于 x 的节点都在大于或等于 x 的节点之前。
    你应当保留两个分区中每个节点的初始相对位置。
    输入: head = 1->4->3->2->5->2, x = 3
    输出: 1->2->2->4->3->5

    思路:双指针
    /**
     * Definition for singly-linked list.
     * public class ListNode {
     *     int val;
     *     ListNode next;
     *     ListNode(int x) { val = x; }
     * }
     */
    class Solution {//执行用时:0 ms, 在所有 Java 提交中击败了100.00%的用户,2020/08/06
        public ListNode partition(ListNode head, int x) {
            ListNode beforeHead = new ListNode(0);
            ListNode before = beforeHead;
            ListNode afterHead = new ListNode(0);
            ListNode after = afterHead;
            while(head != null){
                if(head.val < x){
                    before.next = head;
                    before = before.next;
                }else{
                    after.next = head;
                    after = after.next;
                }
                head = head.next;   
            }
            before.next = afterHead.next;
            after.next = null;
        return beforeHead.next;
        }
    }
    

    相关文章

      网友评论

          本文标题:1.链表(一)

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