算法通关村第1关|链表 青铜挑战

第一关__ 链表 __青铜局

1. 前言

第一关是链表的基本问题,第二关是链表反转以及拓展问题。

2. 重点

  • 算法的基础是数据结构,任何数据结构的基础操作都是创建+增删改查
  • 所以关于学习数据结构,重点首先是前面5个来进行学习算法里的数据结构。
  • 另外,还需要时不时的思考时间复杂度和空间复杂度的问题。

3. 本节要点

  1. 理解Java/Python是如何构造出链表的
  2. 链表增加元素,首部、中间和尾部分别会有什么问题,该如何处理?
  3. 链表删除元素,首部、中间和尾部分别会有什么问题,该如何处理?
  4. 双向链表是如何构造的,如何实现元素的插入和删除

4.链表内部结构JVM构建链表

代码:

public class ListNode {
    public int val;
    public ListNode next;
}

5. 遍历链表

遍历时,从头开始逐个访问

public static int getLength(Node head) {
    int length = 0;
    Node node = head;
    while (node != null) {
        length++;
        node = node.next;
    }
    return length;
}

6. 链表插入

考虑三种情况:

  1. 首部,即表头插入
  2. 中间
  3. 尾部

6.1 表头插入

🎯创建新结点后,要把head重新指向newNode新结点,过程如图所示:

链表插入结点

6.2 中间插入

  • 找到插入节点的前驱结点pre

  • newNode节点指向pre.next,pre指向newNode==(先指向后继,后指向前驱)==

    newNode.next=pre.next;
    pre.next=newNode
    

6.3 尾部插入

  • 尾结点直接指向新结点
  • 新结点指向null

代码实现

 public static Node insertNode(Node head, Node nodeInsert, int position) {
        // 需要判空,否则后面可能会有空指针异常
        if (head == null) {
            return nodeInsert;
        }
        //越界判断
        int size = getLength(head);
        if (position > size + 1 || position < 1) {
            System.out.println("位置参数越界");
            return head;
        }

        //在链表开头插入
        if (position == 1) {
            nodeInsert.next = head;
//            return nodeInsert;
            //上面return还可以这么写:
            head = nodeInsert;
            return head;
        }

        Node pNode = head;
        int count = 1;
        //找到要插入节点的前序结点
        while (count < position - 1) {
            pNode = pNode.next;
            count++;
        }
        nodeInsert.next = pNode.next;
        pNode.next = nodeInsert;

        return head;
    }

值得注意的是,链表插入结点

 		int count = 1;
        //找到要插入节点的前序结点
        while (count < position - 1) {
            pNode = pNode.next;
            count++;
        }
        nodeInsert.next = pNode.next;
        pNode.next = nodeInsert;

7. 链表删除

  • 删表头
  • 删尾结点
  • 删中间结点

7.1 删除表头结点

head=head.next
  • 执行此段代码即可,将head向前移动删除
  • 原来结点会被JVM回收掉

7.2 删除尾结点

  • 同样,需要==找到删除结点的前驱节点==——提前一个位置判断

    举例:

    删除40,前驱结是7,遍历时候需判断cur.next是否为40:若是,执行cur.next=null即可。此时40会被JVM回收

    链表删除尾结点

7.3 删除中间结点

  • 找出删除结点的前驱结点(这里我们统称为cur)
  • cur.next=cur.next.next
/**
 * 删除节点
 *
 * @param head     链表头节点
 * @param position 删除节点位置,取值从1开始
 * @return 删除后的链表头节点
 */
 public static Node deleteNode(Node head, int position) {
        if (head == null) {
            return null;
        }
        int size = getLength(head);
        if (position > size || position <= 0) {
            System.out.println("输入的参数有误");
            return head;
        }

        if (position == 1) {
            // head.next就是链表的新head
            return head.next;
        }
        Node preNode = head;
        int count = 1;
        while (count < position) {
            preNode = preNode.next;
            count++;
        }
        Node curNode=preNode.next;
        preNode.next=curNode;
        return head;
    }
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值