LeetCode链表算法题(java版)


前言

敲敲敲

在写链表的算法题之前先手撕一下链表的几个基本功能吧。(一定要多练习!!!)

class Node{
    
    
    public int data;
    public Node next;
    public Node(int data){
    
    
        this.data = data;
    }
}
public class SingleLinkedList {
    
    
    public Node head;

    //头插法
        public void addFirst(int data){
    
    

            Node node =new Node(data);
            if(this.head==null){
    
    
                this.head=node;
                return;
            }
            node.next=this.head;
            this.head=node;
        }
        
        //打印
    public void display(){
    
    
            Node cur=this.head;
            while(cur!=null){
    
    
                System.out.print(cur.data);
                cur=cur.next;
            }
        System.out.println();
     }


    //尾插法
     public void addEnd(int data){
    
    
            Node node =new Node(data);
            if(this.head==null){
    
    
                this.head=node;
                return;
            }
            Node cur=this.head;
            while(cur.next!=null){
    
    
                cur=cur.next;
            }
            cur.next=node;
     }


     //判断链表中是否存在key值
     public boolean contains(int key){
    
    
            Node cur=this.head;
            while(cur!=null){
    
    
                if(cur.data==key){
    
    
                    return true;
                }
                cur=cur.next;
            }
            return  false;
     }

     //得到链表长度
    public int size(){
    
    
            Node cur=this.head;
            int count=0;
            while(cur!=null){
    
    
                count++;
                cur=cur.next;
            }
            return  count;
    }


    //在index(从1开始的)位置插入元素
    public void addIndex(int index,int data){
    
    
            Node note=new Node(data);
            if(index==0){
    
    
                addFirst(data);
                return;
            }
            if(index==this.size()){
    
    
                addEnd(data);
                return;
            }
            Node cur=this.head;
            while(index-1!=0){
    
    
                cur=cur.next;
                index--;
            }
            note.next=cur.next;
            cur.next=note;
    }


    //删除第一次出现的key值
    public void deleteKey(int key){
    
    
            if(this.head==null){
    
    
               throw new RuntimeException("链表已经空了");
            }
            if(this.head.data==key){
    
    
                this.head=this.head.next;
                return;
            }
            Node prev=searchPrev(key);
            if(searchPrev(key)==null){
    
    
                System.out.println("没有要删除的元素");
                return;
            }
            prev.next=prev.next.next;
    }

    private Node searchPrev(int key){
    
    
            Node prev=this.head;
            while(prev.next!=null) {
    
    
                if (prev.next.data == key) {
    
    
                    return prev;
                } else {
    
    
                    prev = prev.next;
                }
            }
            return null;
        }
        
        
    //删除所有出现的key值
    public void removeAll(int key){
    
    
            if(this.head==null){
    
    
                throw new RuntimeException("链表已经空了");
            }
            Node prev=this.head;
            Node cur=prev.next;
            while(cur!=null){
    
    
                if(cur.data!=key){
    
    
                    prev=prev.next;
                    cur=cur.next;
                }else{
    
    
                    prev.next=cur.next;
                    cur=cur.next;
                }

            }
            if(this.head.data==key){
    
    
                this.head=this.head.next;
            }
    }

   //清空链表
    public void clear(){
    
    
            this.head=null;
    }

}

一、反转链表

题目:
在这里插入图片描述
代码:

class Solution {
    
    
    public ListNode reverseList(ListNode head) {
    
    
        ListNode prev=null;
        ListNode cur=head;
        ListNode newHead=null;
        ListNode curNext=null;
        while(cur!=null){
    
    
            curNext=cur.next;
            if(curNext==null){
    
    
                newHead=cur;   新的链表的头结点就是老链表的头结点
            }
            cur.next=prev;    让后面的节点指向前面的节点完成翻转
            prev=cur;        前驱节点向后移动
            cur=curNext;  cur节点向后移动,curNext相当于一个临时变量储存cur的下一个节点,
        }
        return newHead;
    }
}

二、链表的中间节点(力876)

题目:
## 1.

class Solution {
    
    
    public ListNode middleNode(ListNode head) {
    
    
        ListNode curSlow=head;                         快慢指针法,快指针走两下慢指针走一下,
                                                       只要快指针不为null(奇数个节点)或者快指针
                                                       的下一个节点不为null(偶数个节点)就继续走。
        ListNode curFast=head;
        while(curFast!=null&&curFast.next!=null){
    
    
                curSlow=curSlow.next;
                curFast=curFast.next.next;
        }
        return curSlow;
    }
}

三、倒数第k个节点(剑22)

题目:
在这里插入图片描述

class Solution {
    
    
    public ListNode getKthFromEnd(ListNode head, int k) {
    
    
        ListNode fast=head;
        ListNode slow=head;
        if(k<=0){
    
                      k合法性判断
            return head;
        }                                     
        int n=k-1;                    让快指针先走k-1步,然后快慢指针一起走,当快指针.next为null                                
        while(n>0){
    
                       则停止。此时slow所指向的位置就是要返回的头结点。
            fast=fast.next;
            n--;                     注意一下循环条件中fast!=null指的是最终fast将指向null,而
        }                            fast.next!=null指的是最终fast会指向最后一个节点,这里应该用
        while(fast.next!=null){
    
          后者
            fast=fast.next;
            slow=slow.next;
        }
        return slow;
    }
}

四、分割链表

题目:
在这里插入图片描述

class Solution {
    
    
    public ListNode partition(ListNode head, int x) {
    
    
            ListNode bs=null;
            ListNode be=null;         创建了四个节点分别指向前链表的头尾结点。后链表的头尾节点。cur                     
            ListNode as=null;         用来遍历原始链表。
            ListNode ae=null;
            ListNode cur=head;
            while(cur!=null){
    
              一个一个遍历所有的节点,小于x的插入到前面的链表,大于等于x
                if(cur.val<x){
    
              的插入到后面的链表。    
                    if(bs==null){
    
    
                        bs=cur;
                        be=cur;
                    }else{
    
    
                        be.next=cur;
                        be=be.next;
                    }
                }else{
    
    
                    if(as==null){
    
    
                        as=cur;
                        ae=cur;
                    }else{
    
    
                        ae.next=cur;
                        ae=ae.next;
                    }
                }
                cur=cur.next;
            }
            if(bs==null){
    
                判断要是前面的链表为空,则返回后面的链表的头结点就行了,注意
                if(ae!=null){
    
            把后面链表的尾节点的next置空,不然链表就死循环了。
                    ae.next=null;
                }
                return as;
            }else{
    
                      前面的链表要是不为空
                be.next=as;             就把前面链表的尾结点和后面链表的头结点链接起来
                if(ae!=null){
    
    
                    ae.next=null;      最后把尾结点的next置空
                }
                return bs;
            }
    }
}

五、回文链表

题目:
在这里插入图片描述

class Solution {
    
    
    public boolean isPalindrome(ListNode head) {
    
    
        ListNode slow=head;
        ListNode fast=head;
       // ListNode cur=head;

       if(head==null){
    
               当链表为空力扣默认true牛客默认false
           return true;
       }
       if(head.next==null){
    
          当链表只有一个元素肯定是啦
           return true;
       }
        while(fast!=null&&fast.next!=null){
    
         我们先根据第二题的方法找到链表的中间节点slow
            slow=slow.next;
            fast=fast.next.next;
        }


        ListNode cur=slow.next;                  用cur来遍历从slow开始到null的所有节点,让他们
        while(cur!=null){
    
                            指向自己前面的节点
            ListNode curNext=cur.next;           这里就和反转链表一样了,只不过把前驱结点prev换成
            cur.next=slow;                        了solw
            slow=cur;
            cur=curNext;
        }

        while(head!=slow){
    
                     
            if(head.val!=slow.val){
    
                这时候slow已经指向最后了,不过他这时候已经被翻转
                return false;                  往前指向了,只要不相等就不是回文
            }
            if(head.next==slow){
    
                  判断head.next是不是slow,比如元素个数为偶数1221
                return true;
            }
            head=head.next;                     分别向中间靠拢一个元素
            slow=slow.next;                    
        }
        return true;
    }
}

六、环形链表(力141)

题目:
在这里插入图片描述

public class Solution {
    
    
    public boolean hasCycle(ListNode head) {
    
    
        ListNode slow=head;              定义一个快慢指针指向头结点
        ListNode fast=head;
      
        while(fast!=null&&fast.next!=null){
    
        fast和fast.next都不可以是null,不然就空指针了
            fast=fast.next.next;      快指针一次向后移动两个节点
            slow=slow.next;           慢指针一次向后移动一个节点
            if(fast==slow){
    
               如果快指针和慢指针再次相遇则这是一个环形链表
                return true;   
            } 
            
        }
        return false;

    }
}

七、两个链表的第一个公共节点(剑52)

题目:

public class Solution {
    
    
    public ListNode getIntersectionNode(ListNode headA, ListNode headB) {
    
    
        int len1=0;        
        int len2=0;
        ListNode cur1=headA; 
        while(cur1!=null){
    
    
            len1++;
            cur1=cur1.next;
        }
        ListNode cur2=headB;
        while(cur2!=null){
    
    
            len2++;
            cur2=cur2.next;
        }
        cur1=headA;
        cur2=headB;
        int len=len1-len2;
        if(len1<len2){
    
    
            len=len2-len1;               找到长的链表,让长的链表移动他们差值步
            cur1=headB;                 
            cur2=headA; 
        }
        while(len>0){
    
    
            cur1=cur1.next;
            len--;
        }
        while(cur1!=cur2){
    
                  当不相等就往后走
            cur1=cur1.next;
            cur2=cur2.next;
        }
        if(cur1==cur2&&cur1!=null){
    
             这个时候他们肯定相等,如果不是null就返回cur1
                return cur1;
        }
          return null;
    }
}

八、第一个入环节点(拓展)

题目:
在这里插入图片描述
数学分析一下:
在这里插入图片描述

public class Solution {
    
    
    public ListNode detectCycle(ListNode head) {
    
    
        ListNode slow=head;
        ListNode fast=head;
        while(fast!=null&&fast.next!=null){
    
    
            fast=fast.next.next;
            slow=slow.next;
            if(slow==fast)break;
            }
            if(fast==null||fast.next==null){
    
         找到第一次相遇的地方
                return null;
            }
            slow=head;               让slow从新指向头
            while(fast!=slow){
    
           以相同的速度前进知道下次相遇。
                fast=fast.next;
                slow=slow.next;
            }
            return slow;             第二次相遇的地方就是咱们的入口
        }
    }

九、再熟悉一下链表在ACM模式下的输入输出

 static class ListNode{
    
    
         public int val;
         ListNode next;
        public ListNode(int val) {
    
    
            this.val = val;
        }
        public ListNode(){
    
    };
    }

    public static void main(String[] args) {
    
    

        ListNode head=new ListNode();
        Scanner sc=new Scanner(System.in);
        int n=sc.nextInt();                         //放在数组中进行单链表的遍历输入
        ListNode cur=head;
        int[]nums=new int[n];
        for (int i = 0; i < n; i++) {
    
    
            nums[i]=sc.nextInt();
        }
        for (int i = 0; i <n; i++) {
    
    
            cur.next=new ListNode(nums[i]);        
            cur=cur.next;
        }
        ListNode nx=partition(head, 5);
        ListNode px=nx.next;    //核心代码 从头结点的下一个节点开始遍历。
        while (px!=null){
    
    
            if(px.next!=null){
    
    
                System.out.print(px.val+" ");
                px=px.next;
            }
            else{
    
    
                System.out.println(px.val);
                return;
            }
        }
    }

猜你喜欢

转载自blog.csdn.net/weixin_50302770/article/details/121490212