链表部分小题和双向链表

本文涉及的产品
应用型负载均衡 ALB,每月750个小时 15LCU
传统型负载均衡 CLB,每月750个小时 15LCU
网络型负载均衡 NLB,每月750个小时 15LCU
简介: 链表部分小题和双向链表


1. 环形链表(经典中的经典),返回入环节点,那么我们应该怎么做呢,首先判断链表有没有环,然后是不是空,用经典的快慢指针,快的指针一次走两步,慢的指针走一步,

问题一:先想一下,为什么fast的速度设置为2,slow的速度为1

假如两个有环,他们俩个一定会相遇,因为在环中,fast相当于比slow永远多走一步,也就是说,fast相当于在环里面一直走,slow一直保持原有的位置没有动,所以一定会相遇,所以fast的速度为2在环中会一定和slow相遇

问题二后面的代码是什么意思(不明白看我的图)

fast的速度一直是slow的二倍,所以肯定路程也是二倍(保姆级教学

L是头到环入口的距离,环入口到相遇点的距离是X,M是相遇点到环的入口的距离

力扣142

public class Solution {
    public ListNode detectCycle(ListNode head) {
        ListNode fast=head;
        ListNode slow =head;
        ListNode cur =head;
        if(head==null){                     //判断是否为空
            return null;
        }
        while(fast!=null&&fast.next!=null){//如果没有环,那么一定会有空的时候
            fast=fast.next.next;
            slow=slow.next;
            if(slow==fast){             //把它放后面很细节,是为了不让fast和slow等于头退出
                break;
            }
        }
        if(fast==null||fast.next==null){    //判断是否有环
            return null;
        }
        while(slow!=cur){                   //找环的入口点
            cur=cur.next;
            slow=slow.next;
        }
        return cur;

2.链表相交   很简单思路,把A,B链表走一遍,知道长度差,然后谁长,让谁先走,然后看相不相交

public class Solution {
    public ListNode getIntersectionNode(ListNode headA, ListNode headB) {
        ListNode cur=headA;
        ListNode curv=headB;
        int la=0;                            //a表长度
        int lb=0;                            //b表长度
        if(headB==null&&headA==null){
            return null;
        }
        if(headA==null&&headB!=null||headB==null&&headA!=null){
            return null;
        }
        while(cur!=null){                    //计算A与B的长度
            la++;
            cur=cur.next;
        }
        while(curv!=null){
             lb++;
             curv=curv.next;
        }
        cur=headA;                           //还原两个指针,让他们两个再次指向头
        curv=headB; 
        if(lb>la){
          while(lb-la>0&&curv!=null){      //b长先走   
             curv=curv.next;
             lb--;
            }
        }
        else{
          while(la-lb>0&&cur!=null){
             cur=cur.next;                //a长a先走
             la--;
            }
        }
        while(cur!=null){                     //很重要一个点,相交是点相同,不是点值相同
            if(cur==curv){                    //不要去写.val==.val是不对的
                return cur;
            }
            cur=cur.next;
            curv=curv.next;
            }
            return null;
        }
    }

3.双向链表。要求会写,这是类的必须,其他类中的方法放到下面,内部类是必须要的,然后下面是链表具备的头和尾指针方便插入和删除,(需要分到两个部分写)

下面的各种函数你也都可以用phead就是像c语言那种传一个头之类的。

public class ListNode {
    public class LinkedNode{
        int val;
        LinkedNode next = null;
        LinkedNode prev=null;
        LinkedNode(int val) {
            this.val = val;
        }
}
       public  LinkedNode head;            //链表的头
       public  LinkedNode tail;            //链表的尾巴

3.(1)头插

 // 2、无头双向链表实现
        //头插法
        public void addFirst(int data){
            LinkedNode p=new LinkedNode(data);  申请一个节点
            if(head==null){        //之前的节点为空的话,就头和尾都在开始的节点
                head=p;
                tail=p;
            }
            p.prev=null;          //头节点的前面是NULL
            head.prev=p;          //头连接P节点
            p.next=head;        
            head=p;               //P成为新的头
            tail.next=null;       //尾节点下一个还是null
        }

(2)尾插

 public void addLast(int data){
            LinkedNode p=new LinkedNode(data);    //还是生成个节点
            if(head==null){
                head=p;                           //头和尾都是空
                tail=p;
            }
            while(tail.next!=null){
                tail=tail.next;                  //尾巴遍历到最后
            }
            tail.next=p;                         //tail的下一个连像尾巴节点p
            p.prev=tail;                         //p的前一个节点是尾巴
            tail=p;                              //尾巴指向p
            }

(3)任意位置插入,第一个数据节点为0号下标,插入节点

 public boolean addIndex(int index,int data) {
           if(index<0||index>size()){               //插入序列不合理
               return false;
           }
           LinkedNode cur=head;
           LinkedNode p=new LinkedNode(data);
           int n=1;
           if(index==1){                          //插入第一个就是头插
               addFirst(data);
           }
           while(n<index){
               n++;                              //找到要插入节点的前面
               cur=cur.next;
           }
           if(cur.next.next!=null) {
               p.next=cur.next;                 //插入中间节点
               p.prev=cur;                      //P的前驱后继
               cur.next.prev=p;                  
               cur.next=p;                      //前驱节点的下一个连接他
           }
           else {
               addLast(data);                  //最后一个就是尾插
           }
           return true;
        }

(4)看关键字key在不在链表中(简单的遍历)

 //查找是否包含关键字key是否在单链表当中
        public boolean contains(int key){
            LinkedNode cur=head;
            while(cur!=null){
               if(cur.val==key){
                   return true;
               }
               cur=cur.next;
           }
           return false;
        }

(5)//删除第一次出现关键字为key的节点


//删除第一次出现关键字为key的节点
        public void remove(int key){
            LinkedNode cur=head;
            while(cur!=null){
                if(cur.next.val==key){
                    break;
                }
            }
            cur.next.prev=null;       //key值的前一个点,的前指针为空
            cur.next.next.prev=cur;   //key的后一个节点连key前面的节点
            cur.next=cur.next.next;   //key值的前一个点下一个连接key值的下一个
        }

(6)删除所有值为key的节点(删除全部和上面的删除一个意思一样)

 public void removeAllKey(int key){
            LinkedNode cur=head;
            while(cur!=null){
              if(cur.next.val==key){
                  cur.next.prev=null;
                  cur.next.next.prev=cur;
                  cur.next=cur.next.next;
               }
           }
        }

(7)链表长度和展示(简单不解析了)

  //得到单链表的长度
        public int size(){
            LinkedNode cur=head;
            int n=0;
            while(cur!=null){
                cur=cur.next;
                n++;
            }
            return n;
        }
         public void display(){
            LinkedNode cur=head;
            while(cur!=null){
                System.out.println(cur.val);
                cur=cur.next;
            }
        }


相关实践学习
SLB负载均衡实践
本场景通过使用阿里云负载均衡 SLB 以及对负载均衡 SLB 后端服务器 ECS 的权重进行修改,快速解决服务器响应速度慢的问题
负载均衡入门与产品使用指南
负载均衡(Server Load Balancer)是对多台云服务器进行流量分发的负载均衡服务,可以通过流量分发扩展应用系统对外的服务能力,通过消除单点故障提升应用系统的可用性。 本课程主要介绍负载均衡的相关技术以及阿里云负载均衡产品的使用方法。
相关文章
|
7月前
|
存储 缓存 算法
链表全景:探索单链表、双向链表与循环链表【实战演练】
链表全景:探索单链表、双向链表与循环链表【实战演练】
89 3
|
7月前
|
存储 算法 C语言
线性表,双向链表,静态链表,循环链表(约瑟夫环)(上)
线性表,双向链表,静态链表,循环链表(约瑟夫环)
85 5
数据结构实验之链表九:双向链表
数据结构实验之链表九:双向链表
|
7月前
|
算法 安全 数据处理
LeetCode刷题---707. 设计链表(双向链表-带头尾双结点)
LeetCode刷题---707. 设计链表(双向链表-带头尾双结点)
|
4月前
|
存储 Java
|
5月前
链表8(法二考试专用)7-8 sdut-C语言实验-双向链表
链表8(法二考试专用)7-8 sdut-C语言实验-双向链表
25 0
|
5月前
sdut 链表 8 -----7-8 sdut-C语言实验-双向链表
sdut 链表 8 -----7-8 sdut-C语言实验-双向链表
25 0
|
6月前
|
存储 缓存
【海贼王的数据航海】链表—双向链表
【海贼王的数据航海】链表—双向链表
31 0
|
6月前
|
存储 算法 前端开发
【C/数据结构与算法】:链表的实现(单向链表+双向链表)
【C/数据结构与算法】:链表的实现(单向链表+双向链表)
32 0
|
6月前
|
算法
数据结构和算法学习记录——线性表之双向链表(下)-头插函数、头删函数、查找函数、pos位置之前插入结点、pos位置删除结点及其复用、销毁链表函数
数据结构和算法学习记录——线性表之双向链表(下)-头插函数、头删函数、查找函数、pos位置之前插入结点、pos位置删除结点及其复用、销毁链表函数
33 0

热门文章

最新文章