代码随想录算法训练营第三天|203.移除链表元素、707.设计链表、206.反转链表

代码随想录算法训练营第三天|203.移除链表元素、707.设计链表、206.反转链表

203.移除链表元素

题目链接

问题简述:移除链表值为val的元素。

思考:看起来不难,实际上还是容易出错。leecode链表的题head本身就是内容有效的第一个节点,所以在移除时可以考虑在head前添加虚拟头节点dummy,同时还要考虑循环条件不要出错。

算法思路:当head为空时,直接范围head;当head不为空时,创建一个虚拟头节点,依次遍历每个节点,当数字为val时,删除该节点。

时间复杂度 :O(n)

空间复杂度 :O(1)

/**
 * 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 head;
        }
      //创建虚拟头节点
        ListNode dummy = new ListNode(-1, head);
        ListNode cur = dummy;
      //当cur的下一个结点不为空时,判断下一个结点的值是否为val
        while (cur.next != null){
            if(cur.next.val == val){
                cur.next = cur.next.next;
            }else {
                cur = cur.next;
            }
        }
        return dummy.next;
    }
}

707.设计链表

题目链接

问题简述:设计一个MyLinkList类,该类为一个链表。并实现初始化链表、获取index索引元素值、在头插入结点、尾插入结点、在index索引前添加元素、删除index索引元素。

思考:这道题的索引很容易弄错,题目将第一个有效元素作为索引0,第二个元素索引1。我们在引入虚拟头节点后,第二个结点才是索引0。同时每一个方法的都需要更新链表长度,链表长度为有效元素个数,而不是结点个数。自己在写的时候就是因为忘了更新链表长度所以改了很长时间。

class MyLinkedList {
    int length;
    //head为虚拟头节点
    ListNode head;
//初始化链表
    public MyLinkedList() {
        length = 0;
        head = new ListNode(0);
    }
//得到索引为index的结点值
    public int get(int index) {
      //判断index是否符合要求
        if(index < 0 || index > length - 1){
            return -1;
        }
        ListNode cur = head;
      //一共循环index+1次后,cur正好指向索引为index的结点
        for (int i = 0; i <= index ; i++) {
            cur = cur.next;
        }
        return cur.val;
    }
//头插法添加结点
    public void addAtHead(int val) {
        ListNode newNode = new ListNode(val, head.next);
        head.next = newNode;
        length++;
    }
//尾插法添加结点
    public void addAtTail(int val) {
        ListNode newNode = new ListNode(val);
        ListNode cur = head;
      //循环length次后,cur指向最后一个结点
        for (int i = 0; i < length; i++) {
            cur = cur.next;
        }
        cur.next = newNode;
        length++;
    }
//在index前添加结点val
    public void addAtIndex(int index, int val) {
      //如果index超出范围则返回
        if(index > length) return;
      //如果index恰好等于length,则插入末尾并返回
        if(index == length){
            addAtTail(val);
            return;
        }
        ListNode newNode = new ListNode(val);
      //判断index是否符合要求
        if(index >= 0 && index <= length - 1){
            ListNode cur = head;
          //一共循环index次后,cur正好指向索引为index的前一个结点
            for (int i = 0; i <= index - 1; i++) {
                cur = cur.next;
            }
          //插入到index的前一个位置
            newNode.next = cur.next;
            cur.next = newNode;
            length++;
        }
    }
//删除index结点
    public void deleteAtIndex(int index) {
      //判断index是否符合要求
        if(index >= 0 && index <= length - 1){
            ListNode cur = head;
          //循环index次,cur正好指向索引为index的前一个结点
            for (int i = 0; i <= index - 1; i++) {
                cur = cur.next;
            }
            cur.next = cur.next.next;
            length--;
        }
    }
}

206.反转链表

题目链接

问题简述:得到反转后的链表。

思考:看了视频才知道还有双指针法和递归法,暂时简单看了思路先不写了,等二刷的时候再写。先完成了头插法。

算法思路:将原链表依次头插到新链表中,得到反转链表。

时间复杂度 O(n)

空间复杂度 O(1)

class Solution {
    public ListNode reverseList(ListNode head) {
      //为新链表创立虚拟头节点
        ListNode newhead = new ListNode();
      //为给定链表创立虚拟头节点
        ListNode cur = new ListNode(0, head);
        //当前节点下一个不为空,就把下一个节点头插到新链表
        while (cur.next != null){
          //记录新链表的头
            ListNode p = newhead.next;
          //将旧结点插入新链表
            newhead.next = cur.next;
          //这里我思考过是否会有cur.next.next不存在的情况,因为cur.next != null,即使cur.next.next为空,其仍然存在
            cur.next = cur.next.next;
          //再次接上新链表的虚拟头节点
            newhead.next.next = p;
        }
        return newhead.next;
    }
}

感想

感觉这几道题没用到太复杂的思想,但是稍不留神还是很容易出错,关键在于循环条件。

  • 3
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值