快慢指针解决链表问题以及常见链表算法题分享

快慢指针介绍

假设给你一个链表的头节点如果要求你只能遍历一遍链表把这个链表的中中点找出来那应该怎么做呢?
这时候我们就可以使用快慢指针来做了

首先我们先创建两个和头节点一样的两个引用,我们一般正常遍历不是一个一个节点的遍历吗,我们把这个两个引用其中一个每次走一步,另一个节点每次走两步,当每次走两步的节点走到尾节点时每次走一步的那个引用所在的位置就在中点位置,
这两个引用一个是另一个的两倍所以当快的那个引用走到终点时慢的引用就走了一半
所以我们可以用这种方法来找链表的中点位置:

代码实现

class Node{
    public int a;
    public Node node;
    public Node node1;
    public Node next;
    public void set(int k){
        if(node ==null){
            node = new Node();
            node1 = node;
            node.a = k;
            return;
        }
        node1.next = new Node();
        node1 = node1.next;
        node1.a = k;
    }
    public void print(){
        Node node2 = node;
        while (node2!=null){
            System.out.println(node2.a);
            node2 = node2.next;


        }


    }

}
public class t {
    public static void main(String[] args) {
        Node aa = new Node();
      for(int i = 1;i<=4;i++){
          aa.set(i);

      }

        Node f =k3(aa.node);
        System.out.println(f.a);

    }
    public static Node kk(Node head){    //奇数返回中点偶数返回上中点
        Node node = head;
        Node node1 = head;
        if(head.next.next ==null){
            return head;
        }
        while (node!=null){
            if(node.next!=null){
                node = node.next.next;
            }else {
                break;
            }
            if(node!=null){
                node1 = node1.next;
            }



        }
        return node1;


    }
    public static Node k2(Node head){  //奇数点返回中点偶数返回下中点
        Node node= head;
        Node node1 = head;
        if(head.next.next ==null){
            return head.next;

        }
        while (node!=null){
            if(node.next!=null){
                node = node.next.next;
                node1 = node1.next;
            }else {
                break;
            }

        }
        return node1;


    }
    public static Node k3 (Node head){ //奇数点返回中点前一个,偶数点返回上中点
          Node node = head;
          Node node1 = head;
          Node node2 = null;
          if(head.next.next ==null){
              return head;
          }
          while (node!=null){
              if(node.next !=null){
                  node =node.next;
              }else {
                  break;
              }
              if(node.next!=null){
                  node = node.next;
                  if(node.next==null){
                     break;

                  }

                  node1 = node1.next;


              }else {
                  break;
              }


          }
          return node1;

    }
    public static Node k4(Node head){ //奇数返回中点前一个偶数返回下中点
        Node node = head;
        Node node1 = head;

        while (node!=null){
            if(node.next!=null){
                node = node.next;

            }else {
                break;
            }
            if(node.next!=null){
                node = node.next;
                if(node.next ==null){

                    break;
                }
                node1 = node1.next;
            }else {
                node1 = node1.next;
                break;
            }

        }
        return node1;


    }






}

这里实现了好几种方

常见链表算法题

这里的题会拿两种方式实现

回文链表

判断一个链表是不是回文链表:例如:a->b->a;这个就是回文的a->c->d;这个就不是;回文大意就是正着读和倒着读是一样的

解法一;
用容器来实现(一般在比试的时候使用,面试不推荐)
解题大意:
先创建一个栈,然后遍历来链表把链表中所有的元素放入栈中,然后再遍历一次这次遍历要和出栈元素做作比较,出栈其实就是把链表从后往前遍历,这样就能判断这个链表从后往前和从前往后是不是一样的,进一步判断是不是回文链表

代码实现:

import java.util.Stack;

class Node{
    public int a;
    public Node node;
    public Node node1;
    public Node next;
    public void set(int k){
        if(node ==null){
            node = new Node();
            node1 = node;
            node.a = k;
            return;
        }
        node1.next = new Node();
        node1 = node1.next;
        node1.a = k;
    }
    public void print(){
        Node node2 = node;
        while (node2!=null){
            System.out.println(node2.a);
            node2 = node2.next;


        }


    }

}
public class t {
    public static void main(String[] args) {
        Node aa = new Node();
        aa.set(1);
        aa.set(2);
        aa.set(1);
        aa.set(1);
        aa.set(2);
        aa.set(1);

        boolean f = pan(aa.node);
        System.out.println(f);


    }
    public static boolean pan(Node head){
        Node node = head;
        Stack<Integer> a = new Stack<>();
        while (node !=null){ //把所有元素入栈
            a.push(node.a);
            node = node.next;

        }
        node = head;
        while (node!=null){ //判断出栈元素和链表对应元素是否相等

            if(node.a!=a.pop()){
                return false;
            }
            node = node.next;

        }
        return true;


    }
}

代码里我创建的链表元素是整形;

解法二:
接替大意:先遍历一遍链表找到中点位置,然后从尾节点到中点的所有节点往前指
在这里插入图片描述
代码实现:

import java.util.Stack;

class Node{
    public int a;
    public Node node;
    public Node node1;
    public Node next;
    public void set(int k){
        if(node ==null){
            node = new Node();
            node1 = node;
            node.a = k;
            return;
        }
        node1.next = new Node();
        node1 = node1.next;
        node1.a = k;
    }
    public void print(){
        Node node2 = node;
        while (node2!=null){
            System.out.println(node2.a);
            node2 = node2.next;


        }


    }

}
public class t {
    public static void main(String[] args) {
        Node aa = new Node();
        aa.set(1);
        aa.set(2);
        aa.set(3);
        aa.set(2);

        aa.set(1);
        aa.print();

       boolean f  =pan(aa.node);

        System.out.println(f);
     
    }
    public static boolean pan(Node head){
        Node mid = zhong(head);
        Node node  = mid;
        Node wei = null;


        if(mid.next.next==null){
            if(head==mid){
                if(head.a ==mid.a){
                    return true;
                }else {
                    return false;
                }
            }else {
                return mid.next.a==head.a;
            }

        }
        Node node1 = node.next;
        Node node2 = node1.next;
        while (node2!=null){

            node1.next = node;
            node = node1;
            node1 = node2;
            if(node2.next==null){
                wei  =node2;

            }
            node2 = node2.next;



        }
        Node H = head;

        wei.next = node;
        while(wei!=mid){
            if(H.a !=wei.a){
                return false;
            }
            H =H.next;
            wei = wei.next;

        }
        fuyuan(head,mid,node1);


        return true;


    }
    public static void fuyuan(Node head,Node mid,Node wei){//复原链表
        Node node = wei;
        Node node1 = wei.next;
        Node node2 = node1.next;
        if(node2 ==mid){
            node1.next = node;
            node.next =null;

            return;
        }else {

            while (node2 != mid) {


                node1.next = node;

                node = node1;
                node1 = node2;
                node2 = node2.next;


            }
            node1.next = node;
            wei.next =null;

        }












    }
    public static Node zhong(Node head){ //奇数节点数返回中点位置,偶数返回上中点位置
        Node node = head;
        Node node1 = head;
        while (node !=null){
            if(node.next!=null){
                node = node.next.next;

            }else {
                break;
            }
            if(node !=null){
                node1 = node1.next;

            }



        }
        return node1;


    }

}

说明一下我这里最后复原原链表是如果是回文的才执行这个函数。至于不是回文的我没设置

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值