【算法通关村】第一关链表青铜挑战笔记

时间复杂度

时间复杂度是语句执行的次数,而不是实际时间。

时间复杂度针对执行的次数与问题的规模之间的关系来看的。

凡是处理时间复杂度,一定要注意一点:那就是代码体与循环结束条件之间的关系。

第一关 链表基础

单链表

概念

结点相连,每个结点包含元素的值和指向下一个结点的next指针。最后一个结点的next指向null。一个结点只能有一个后继,但不代表一个结点只能有一个被指向

做题的时候要注意比较的是值还是结点,有时可能两个结点的值相等,但并不是同一个结点。

  • 头结点:第一个结点,可以通过它访问整个链表

  • 虚拟结点:为了方便我们处理首部结点。*注意:如果要获得head结点,或者从方法(函数)里返回的时候,则应使用dummyNode.next

创建列表

 public class ListNode {
     public int val;
     public ListNode next;
     
     ListNode(int x) {
         val = x;
         next = null;
     }
 }
 ListNode listnode = new ListNode(1);

遍历链表

”狗熊掰棒子“ 注意别忘记标记表头的指针。

 public static int getListLength(Node head){
     int len=0;
     Node cur = head; //标记一下
     while(cur!=null){
         len++;
         node = node.next;
     }
     return len;
 }

链表插入

在表头插入
  1. 创建新节点

  2. 新结点.next = head

  3. head = 新节点 (head要重新指向表头!!!不管用head更简单,因为head变了之后,后续操作不好实现)

在链表中间插入
  1. 在要删除的结点前一个位置停下, cur.next来判断

     //while循环,下标从1开始的链表
     Node pNode = head;
     int count =1;
     while(count < position - 1){
         pNode = pNode.next;
         count++;
     }
  2. 创建新结点

  3. 新结点.next = pNode.next

  4. pNode.next = 新结点

在表尾插入

简单。尾结点.next = 新结点。

链表删除

在表头删除

简单。把head往后移动一位。

在表中删除

preNodepreNode.next = preNode.next.next

删除尾结点

preNode,将preNode.next == null

MyBasicLinkList

  • 实现:

    • 创建链表2 3 4 6

    • 插入5,保持升序 (插入1 插入7)

    • 删除1 4 6

  • 问题:

    • 升序插入7,边界问题怎么搞?(已解决)

    • 一次次插入好麻烦,一次次删除好麻烦,能否优化?

public class MyBasicLinkList {
    //创建结点
    public static class Node {
        public int val;
        public Node next;

        public Node(int val) {
            this.val = val;
            this.next = null;
        }
    }

    //main函数,创建2 3 4 6      插入1,保持升序       删除1 4 6
    public static void main(String[] args) {
        //创建2 3 4 6
        Node head = new Node(2);
        System.out.print("链表现在为:");
        Node node = new Node(3);
        InsertNode(head,node,2);
        node = new Node(4);
        InsertNode(head,node,3);
        node = new Node(6);
        InsertNode(head,node,4);
        MyBasicLinkList.printLink(head);
        System.out.println(" ");
        //插入1保持升序
        node = new Node(1);
        head = SpecialInsertNode(head,node);  //记得重新定义head!!!
        System.out.print("链表现在为:");
        MyBasicLinkList.printLink(head);
        //删除1 4 6
        head = deleteNode(head,1);
//        head = deleteNode(head,4);
//        head = deleteNode(head,5);           脑子糊涂了,删除之后position也会变,佛了,好麻烦
        System.out.print("链表现在为:");
        MyBasicLinkList.printLink(head);

        head = deleteNode(head,3);
        System.out.print("链表现在为:");
        MyBasicLinkList.printLink(head);

        head = deleteNode(head,3);
        System.out.print("链表现在为:");
        MyBasicLinkList.printLink(head);

    }

    //输出链表
    public static void printLink(Node head){
        Node cur = head;
        while(cur!=null){
            System.out.print(cur.val+" ");
            cur = cur.next;
        }
    }

    //获取链表长度
    public static int getLength(Node head){
        int len=0;
        Node node = head;
        while(node!=null){
            node = node.next;
            len++;
        }
        return len;
    }

    //插入结点
    public static Node InsertNode(Node head, Node nodeInsert, int position){
       //判断是否为空链表
        if(head==null){
            return nodeInsert;
        }
        //判断是否数组越界
        int size = getLength(head);
        if(position>size+1||position<0){
            System.out.println("数组越界");
            return head;
        }
        //在开头插入
        if(position == 1){
            nodeInsert.next = head;
            head = nodeInsert;
            return head;
        }
        //在中间插入,包括在尾部插入
        //找preNode
        Node preNode = head;
        int count =1;
        while(count < position - 1){
            preNode = preNode.next;
            count++;
        }
        nodeInsert.next = preNode.next;
        preNode.next = nodeInsert;

        return head;
    }
    //升序插入
    public static Node SpecialInsertNode(Node head, Node nodeInsert){
        //处理head
        if(head == null){
            return nodeInsert;
        }
        if(head.val > nodeInsert.val){
            nodeInsert.next = head;
            head = nodeInsert;
            return head;
        }
        //找preNode下标
        Node cur = head;
        while(cur.next.val< nodeInsert.val){
            cur = cur.next;
            if(cur.next == null){         //处理插入到最后的情况
                cur.next = nodeInsert; 
                return head;
            }
        }
        nodeInsert.next = cur.next;
        cur.next = nodeInsert;
        return head;
    }

    //删除结点
    public static Node deleteNode(Node head,int position){
        if(head==null){
            return null;
        }
        int size=getLength(head);
        if(position>size||position<1){ //size  不是size+1     因为可删除的结点下标范围是[1,size]  size+1越界了,删个寂寞
            System.out.println("数组越界");
            return head;
        }
        if(position==1){
            head = head.next;
            return head;
        } else {
            Node cur = head;
            int count = 1;
            while (count < position - 1) {
                cur = cur.next;
                count++;
            }
            cur.next = cur.next.next;
        }
        return head;

    }

}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值