每日刷题记录(二)

目录

  • 第一题:删除链表中等于给定值 val 的所有节点
    • 解题思路:
    • 代码实现:
  • 第二题:反转单链表
    • 解题思路:
    • 代码实现:
  • 第三题:链表的中间节点
    • 解题思路:
    • 代码实现:
  • 第四题:链表中倒数第k个节点
    • 解题思路:
    • 代码实现:
  • 第五题:合并两个有序链表
    • 解题思路:
    • 代码实现:

第一题:删除链表中等于给定值 val 的所有节点

给你一个链表的头节点 head 和一个整数 val ,请你删除链表中所有满足 Node.val == val 的节点,并返回 新的头节点。
示例 1:

输入:head = [1,2,6,3,4,5,6], val = 6
输出:[1,2,3,4,5]

示例 2:

输入:head = [], val = 1
输出:[]

示例 3:

输入:head = [7,7,7,7], val = 7
输出:[]

提示:

  • 列表中的节点数目在范围 [0, 104] 内
  • 1 <= Node.val <= 50
  • 0 <= val <= 50

解题思路:

  1. 判断链表是否为空
  2. 用prev和cur分别指向head和head,如果cur.val等于val,令prev.next=cur.next,删除cur节点,cur向后移动一步,如果不相等,cur和prev向后移动一步
  3. 最后判断head.val值与val是否相等

代码实现:

/**
 * 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 removeElements(ListNode head, int val) {
        if(head == null) {
            return null;
        }
        ListNode prev = head;
        ListNode cur  = head.next;
        while(cur != null) {
            if(cur.val == val) {
                prev.next = cur.next;
                cur = cur.next;
            }else {
                prev = cur;
                cur = prev.next;
            }
        }
        if(head.val == val) {
            head = head.next;
        }
        return head;
    }
}

第二题:反转单链表

给你单链表的头节点 head ,请你反转链表,并返回反转后的链表。

示例 1:

输入:head = [1,2,3,4,5]
输出:[5,4,3,2,1]

示例 2:

输入:head = [1,2]
输出:[2,1]

示例 3:

输入:head = []
输出:[]

提示:

  • 链表中节点的数目范围是 [0, 5000]
  • -5000 <= Node.val <= 5000

解题思路:

  1. 判断链表是否为空或只有一个节点
  2. 令cur指向head.next,head.next置为null,令curNext指向cur.next,用头插法将cur连接head,将head指向cur,cur指向curNext

代码实现:

/**
 * 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 reverseList(ListNode head) {
       if(head == null) {
           return null;
       }
       if(head.next == null) {
           return head;
       }
       ListNode cur = head.next;
        head.next = null;
        ListNode curNext;
        while(cur != null) {
            curNext = cur.next;
            cur.next = head;
            head = cur;
            cur = curNext;
        }
        return head;
    }
}

第三题:链表的中间节点

给你单链表的头结点 head ,请你找出并返回链表的中间结点。
如果有两个中间结点,则返回第二个中间结点
示例 1:

输入:head = [1,2,3,4,5]
输出:[3,4,5]
解释:链表只有一个中间结点,值为 3 。

示例 2:

输入:head = [1,2,3,4,5,6]
输出:[4,5,6]
解释:该链表有两个中间结点,值分别为 3 和 4 ,返回第二个结点

提示:

  • 链表的结点数范围是 [1, 100]
  • 1 <= Node.val <= 100

解题思路:

  1. 用两个指针 slow 与 fast 一起遍历链表
  2. slow 一次走一步,fast 一次走两步。那么当 fast 到达链表的末尾时,slow 必然位于中间

代码实现:

/**
 * 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 middleNode(ListNode head) {
        ListNode fast = head;
        ListNode slow = head;
        while(fast != null&&fast.next != null) {
                fast = fast.next.next;
                slow = slow.next;
        }
        return slow;
    }
}

第四题:链表中倒数第k个节点

描述
输入一个链表,输出该链表中倒数第k个结点。
示例1

输入: 1,{1,2,3,4,5}
返回值: {5}

解题思路:

  1. 判断k的合法性
  2. 用两个指针 slow 与 fast 一起遍历链表,fast先走k-1步
  3. 当fast.next不为空时,fast和low向后走一步,循环结束后返回low

代码实现:

/**
 * Definition for singly-linked list.
 * public class ListNode {
 *     int val;
 *     ListNode next;
 *     ListNode(int x) { val = x; }
 * }
 */
class Solution {
    public ListNode getKthFromEnd(ListNode head, int k) {
        ListNode fast = head;
        ListNode slow = head;
        if(k <= 0||head == null) {
            return null;
        }
        while(k-1 != 0) {
            if(fast.next == null) {
                return null;
            }
            fast = fast.next;
            k--;
        }
        while(fast.next != null) {
            fast = fast.next;
            slow = slow.next;
        }
        return slow;
    }
}

第五题:合并两个有序链表

将两个升序链表合并为一个新的 升序 链表并返回。新链表是通过拼接给定的两个链表的所有节点组成的。
示例 1:

输入:l1 = [1,2,4], l2 = [1,3,4]
输出:[1,1,2,3,4,4]

示例 2:

输入:l1 = [], l2 = []
输出:[]

示例 3:

输入:l1 = [], l2 = [0]
输出:[0]

提示:

  • 两个链表的节点数目范围是 [0, 50]
  • -100 <= Node.val <= 100
  • l1 和 l2 均按 非递减顺序 排列

解题思路:

  1. 判断两个链表是否为空
  2. 实例一个傀儡节点newNode,使tmp引用newNode,判断list1和list2val值的大小,令tmp.next等于val值小的list,tmp向后移动一步,list向后移动一步
  3. 循环结束后,list1和list2可能不为空,分别判断,若list1为空,list2不为空,tmp.next指向list2,最后返回newNode.next

代码实现:

/**
 * 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 newNode = new ListNode();
        ListNode tmp = newNode;
        while(list1 != null&&list2 != null) {
            if(list1.val < list2.val) {
                tmp.next = list1;
                tmp = tmp.next;
                list1 = list1.next;
            }else {
                tmp.next = list2;
                tmp = tmp.next;
                list2 = list2.next;
            }
        }
        if(list1 != null) {
            tmp.next = list1;
        }
        if(list2 != null) {
            tmp.next = list2;
        }
        return newNode.next;
    }
}

你可能感兴趣的:(在线OJ,链表,数据结构,java)