LeetCode链表算法题(java版)

Posted 3 ERROR(s)

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了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)

题目:

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]=scLeetCode与《代码随想录》双指针篇:做题笔记与总结-JavaScript版

LeetCode数组算法题(Java版)

2020年面试算法题合集(北京中小公司版)持续更新

leetcode刷题55.环形链表——Java版

leetcode刷题6.合并有序链表——Java版

leetcode刷题18.反转链表——Java版