leetcode打卡4.9

 春招笔试手撕链表题没有做出来,我练我练我使劲练

[21. 合并两个有序链表] 将两个升序链表合并为一个新的 升序 链表并返回。新链表是通过拼接给定的两个链表的所有节点组成的。

方法一:迭代法

/**
 * Definition for singly-linked list.
 * public class ListNode {
 *     int val;
 *     ListNode next;
 *     ListNode() {}
 *     ListNode(int val) { this.val = val; }
 *     ListNode(int val, ListNode next) { this.val = val; this.next = next; }
 * }
 */
class Solution {
    public ListNode mergeTwoLists(ListNode list1, ListNode list2) {
        ListNode head = new ListNode();
        ListNode res = head;
        while(list1 != null && list2 != null) {
            if(list1.val > list2.val) {
                res.next = list2;
                list2 = list2.next;
            }
            else{
                res.next = list1;
                list1 = list1.next;
            }
            res = res.next;
        }
        // list1或list2可能没合并完
        res.next = list1 != null ? list1 : list2;
        return head.next;
    }
}

方法二:递归

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;
        }
    }
}

解题思路:

        由于两个链表都是有序的,因此可以新建一个链表来存放合并后的结果,通过依次对比两个链表的值,将较小的值直接加入新建的链表。迭代条件为list1或list2当前不为空。注意在跳出循环后判断list1或list2是否合并完。

复杂度分析:

  • 时间复杂度: O(n+m),其中 n 和 m分别为两个链表的长度
  • 空间复杂度:迭代O(1),只需要常数的空间存放若干变量。递归O(n+m)

[142. 环形链表 II]

给定一个链表的头节点  head ,返回链表开始入环的第一个节点。 如果链表无环,则返回 null

如果链表中有某个节点,可以通过连续跟踪 next 指针再次到达,则链表中存在环。 为了表示给定链表中的环,评测系统内部使用整数 pos 来表示链表尾连接到链表中的位置(索引从 0 开始)。如果 pos-1,则在该链表中没有环。注意:pos 不作为参数进行传递,仅仅是为了标识链表的实际情况。

不允许修改 链表。

/**
 * 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) {
        ListNode l1 = head;
        ListNode l2 = head;
        // 如果是换,则一定会相遇
        while(l2 != null && l2.next != null) {
            l1 = l1.next;
            l2 = l2.next.next;
            if(l1 == l2) {
                // 让慢指针回到原点出发,快指针再相遇的点出发,两指针再次相遇的点就是入环的第一个节点
                l1 = head;
                while(l1 != l2) {
                    l1 = l1.next;
                    l2 = l2.next;
                }
                return l1;
            }
        }
        return null;
    }
}

解题思路:

      代码随想录这篇讲解很好 . - 力扣(LeetCode)

        这一次独立完成,主要还是要画图分析出快慢指针间的关系,总结来说,定义慢指针一次走一步,快指针一次走两步,如果链表是环形的,则两者一定会相遇;若链表不是环形的,则一定存在慢指针slow = null 或 slow.next = null。若判断链表是环形的,通过公式可以推断出,若将慢指针放回原点出发,快指针放在相遇点出发,步长为一步,它们再次相遇的点即为环形链表入口。

复杂度分析:

  • 时间复杂度: O(n),其中 n 表示链表的长度
  • 空间复杂度:O(1)

[19. 删除链表的倒数第 N 个结点]

笨方法:

/**
 * Definition for singly-linked list.
 * public class ListNode {
 *     int val;
 *     ListNode next;
 *     ListNode() {}
 *     ListNode(int val) { this.val = val; }
 *     ListNode(int val, ListNode next) { this.val = val; this.next = next; }
 * }
 */
class Solution {
    public ListNode removeNthFromEnd(ListNode head, int n) {
        // 遍历链表,获取长度
        int len = 0;
        ListNode dummy = new ListNode(0);
        dummy.next = head;
        ListNode temp1 = head;
        while(temp1 != null) {
            len++;
            temp1 = temp1.next;
        }
        // 删除第正数len-n+1个
        temp1 = dummy;
        for(int i = 0; i < len - n; i++) {
            temp1 = temp1.next;
        }
        temp1.next = temp1.next.next != null ? temp1.next.next : null;
        return dummy.next;
    }
}

解题思路:

      先遍历链表获取链表长度要删除的数的正索引,然后顺序遍历删除。

复杂度分析:

  • 时间复杂度: O(n),其中 n 表示链表的长度
  • 空间复杂度:O(1)

方法二:快慢指针

/**
 * 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 pre = new ListNode(0);
        pre.next = head;
        ListNode start = pre, end = pre;
        while(n != 0) {
            start = start.next;
            n--;
        }
        while(start.next != null) {
            start = start.next;
            end = end.next;
        }
        end.next = end.next.next;
        return pre.next;
    }
}

解题思路:. - 力扣(LeetCode)

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值