链表的实现及其相关习题

本文介绍了链表的基本实现,并详细讲解了如何解决LeetCode中的链表相关问题,包括反转链表、回文链表、环形链表、删除指定元素、相交链表和合并有序链表等经典题目,强调掌握链表操作的重要性以及解题思路的独特性。
摘要由CSDN通过智能技术生成

@TOC链表的实现及其相关习题


前言

1.链表的实现:

		下文我通过递归实现
		(在寻找Last元素时while循环也是可以的)

2.常见链表相关习题:【均来自LeetCode题库】

		(1)反转链表。
		
		(2)回文链表
		
		(3)环形链表
		
		(4)删除链表指定元素
		
		(5)相交链表
		
		 (6)合并两个有序链表(排好序的)

二、常见链表相关习题:

1.单向链表的实现

public class MyLinkList{
    //头节点
    private LinkNode first=new LinkNode(null,null);
    private int sive;
    //添加元素
    public MyLinkList(){}
    // 添加元素
    public void add(Object obj){
        if(first.next==null){
            first.next=new LinkNode(obj,null);
        }else{
            LinkNode lastNode=SearchlastNode(first.next);
            lastNode.next=new LinkNode(obj,null);
        }
        sive++;
    }
    private LinkNode SearchlastNode(LinkNode first){
        LinkNode node=first;
        while(true){
            if(node.next==null){
                return node;
            }
            node=node.next;
        }
    }
    // 在头节点增加元素
    public void addHeadNode(Object obj){
        if (first.next==null){
            add(obj);
        }else {
            first.next=new LinkNode(obj,first.next.next);
        }
        sive++;
    }
    // 删除头节点
    public boolean deleteHeadNode(){
        if(first.next==null){
            return false;
        }else {
            first.next=first.next.next;
            sive--;
            return true;
        }
    }

    // 查询链表中元素的个数
    public int size(){
        return this.sive;
    }
    // 删除指定元素
    public boolean delete(Object obj){
        if(first.next==null){
            return false;
        }
        LinkNode node=first.next;
        while(node!=null){
            if(obj.equals(node.date)){
                return true;
            }
            node=node.next;
        }
        return false;
    }
    // 在指定元素后增加新元素
    public boolean appointAdd(Object obj,Object newobj){
            if(first.next==null){
                return false;
            }

            LinkNode node=first.next;
            while(node!=null){
                if(obj.equals(node.date)){
                    if(node.next==null){
                        node.next=new LinkNode(newobj,null);
                        return true;
                    }
                    node.next=new LinkNode(newobj,node.next.next);
                    return true;
                }
                node=node.next;
            }
            return false;
    }
}

class LinkNode {
    public Object date;
    public LinkNode next;
    public LinkNode(Object obj, LinkNode next){
        // 是梦开始的起点也是 所有过程的必经之路!!
        this.next=next;
        this.date=obj;
    }
    @Override
    public String toString() {
        return (String) date;
    }
}

2.链表相关习题

(1).反转链表:(LeetCode题目编号:206)
这里我采用三指针移动的方法解决(当然也可以暴力递归或者循环)
如图:
在这里插入图片描述
在这里插入图片描述

代码如下:

* public class ListNode {
 *     int val;
 *     ListNode next;
 *     ListNode(int x) { val = x; }
 * }

class Solution {
	public ListNode reverseList(ListNode head) {
		return help(head);
    }
    public ListNode help(ListNode head){
            if(head==null || head.next==null)return head;
            if(head.next.next==null){
                ListNode jj=head;
                ListNode ii=jj.next;
                ii.next=jj;
                jj.next=null;
                return ii;
            }
            ListNode i,j,t;
            i=head;
            j=head.next;
            t=head.next.next;
            i.next=null;
            while(true){
                j.next=i;
                i=j;
                if(t==null)break;
                j=t;
                t=t.next;
            }
            return j;
    }
}

还可以暴力递归 你们随便看看就行(虽然也可以但是空间,时间复杂度都比较大)
简单来说就是先遍历存储到栈中再递归弹栈形成反转链表newhead
在这里插入图片描述

class Solution {
     ListNode   newhead;
     Stack<ListNode> stack;
    public ListNode reverseList(ListNode head) {
         if(head==null)return null;
         Stack<ListNode> stack=new Stack<>();
         while(head!=null){
             stack.push(head);
       	     head=head.next;
         }
         this.stack=stack;
         this.newhead=this.stack.pop();
         return digui(newhead);
    }
     public ListNode digui(ListNode head){
        if(!this.stack.isEmpty()){
             head.next=this.stack.pop();
             return digui(head.next); 
         }else{
            head.next=null;
             return this.newhead;
         }
     }
}

(2)回文链表:(LeetCode题目编号:234)

1.先展示一个效率比较低但是很好理解的方法:(效率高的版本博主尚未理解和哈哈哈哈实现嘻嘻!)

在这里插入图片描述

/**
 * Definition for singly-linked list.
 * public class ListNode {
 *     int val;
 *     ListNode next;
 *     ListNode(int x) { val = x; }
 * }
 */
class Solution {
    public boolean isPalindrome(ListNode head) {
    //new一个双端队列   
        ArrayDeque<ListNode> deque=new ArrayDeque<>();
        //将链表中的元素循环存入双端队列中
        while(head!=null){
            deque.addFirst(head);
            head=head.next;
        }
        //再 循环出列判断首尾是否一致  若不一致则直接返回false
        while(!deque.isEmpty()){
        /*
        这里我们需要考虑到最后firs出列和last出列为同一个对象的情况   
        相当于正好走到了队列的正中央 

		removeFirst()方法会检索队列首元素并删除
		getFirst()方法会检索队列首元素但不删除
		removeLast()与getLast()同理
		*/
            if(deque.getFirst()==deque.getLast())return true;
            if(deque.removeFirst().val != deque.removeLast().val) return false;
        }
        return true;
    }
} 

(3)环形链表:(LeetCode题目编号:141)
这一题配图会好理解一些:
在这里插入图片描述

		这一题咋们不得不说快慢指针了:(以下是我形象的解释哈哈哈)
			假设乌龟和兔子起点都在头节点						
    快慢指针:
            乌龟跑的慢  所以   乌龟是后进入环的
            兔子跑的快  所以   兔子是先进入环的
            当两者都进入环
            **兔子一定会追乌龟(因为兔子跑的快嘛!!)
            当乌龟与兔子相遇则
            存在环
            若兔子走到了null(如果没环那大家都没进入环  最终都走到了最后一个节点 next==null;)
            则无环
 
						代码如下:(实力有限,我写的并不太简洁)

在这里插入图片描述

/**
 * Definition for singly-linked list.
 * class ListNode {
 *     int val;
 *     ListNode next;
 *     ListNode(int x) {
 *         val = x;
 *         next = null;
 *     }
 * }
 */
public class Solution {
    LinkedList list=new LinkedList();
    public boolean hasCycle(ListNode head) {
        ListNode l1=head;
        if(l1==null){
return false;
        }
        ListNode l2= head.next;
        if (l2==null ||l2.next==null || l2.next.next==null){
            return false;
        }
        
        while(true){
            if (l2.next==null || l2.next.next==null){
                return false;
            }
            if(l1.equals(l2)){
                return true;
            }
            l1=l1.next;
            l2=l2.next.next;
        }
    }
}

(4)删除链表指定元素:(LeetCode题目编号:203)
我是暴力递归可能有点难理解 需要你细心阅读
当然也可以循环实现 (博主脑子中毒了)
在这里插入图片描述

/**
 * Definition for singly-linked list.
 * public class ListNode {
 *     int val;
 *     ListNode next;
 *     ListNode(int x) { val = x; }
 * }
 */
class Solution {
    int val;
    ListNode head;
    public ListNode removeElements(ListNode head, int val) {
            this.head=head;
            this.val=val;
            // 一个都没有
            if(head==null){
                return head;
            }
            // 正好只有一个
            if(head.next==null){
                if(head.val==val){
                    head=null;
                    return head;
                }
                return head;
            }
            // 两个及两个以上
            return removeElementsGo(head);
    }
    public ListNode removeElementsGo(ListNode head){
        if(head==null){
            return this.head;
        }
        if(this.head.val==this.val){
            this.head=head.next;    
            head=null;
            return removeElementsGo(this.head);
        }
        if(head.next==null && head.val==this.val){
                head=null;
                return this.head;
        }else if(head.next==null){
                return this.head;
        }
        if(head.next.val==this.val){
            head.next=head.next.next; 
            return removeElementsGo(head);
        }else{
            return removeElementsGo(head.next);
        }
    }
}

(5)相交链表:(LeetCode题目编号:160)

	这一题也上图吧:

在这里插入图片描述
我也是暴力解法嘻嘻:
意思就是 先算每个链表的长度n1,n2 再让较长的链表先走|n1-n2|步
然后同起点进行逐个判断是否相交 如果不相交 最终都走到尾节点 next=null;

在这里插入图片描述

代码如下:

/**
 * Definition for singly-linked list.
 * public class ListNode {
 *     int val;
 *     ListNode next;
 *     ListNode(int x) {
 *         val = x;
 *         next = null;
 *     }
 * }
 */
public class Solution {
    public ListNode getIntersectionNode(ListNode headA, ListNode headB) {
        if(headA==null || headB==null)return null;
        int a=length(headA);
        int b=length(headB);
        if(a>b){
            return getIntersectionNodeGo(headA,headB,a,b);
        }else if(a<b){
            return getIntersectionNodeGo(headB,headA,b,a);
        }else{
            ListNode i=headA;
            ListNode j=headB;
            while(true){
                if(i==null || j==null){
                    return null;
            }
                if(i.equals(j)){
                    return i;
            }
                
                i=i.next;
                j=j.next;
            }
        }
    }
    public int length(ListNode head){
        int length=0; 
        while(head!=null){
            length++;
            head=head.next;
        }
        return length;
    }
    public ListNode getIntersectionNodeGo(ListNode headA, ListNode headB,int a,int b){
        ListNode i=headA;
        ListNode j=headB;
        while(true){
              i=i.next;
              a--;
              if(a==b)break;
        }
        while(true){
            if(i==null || j==null){
                return null;
            }
            if(i.equals(j)){
                return i;
            }
            i=i.next;
            j=j.next;
        }
    }
}

(6)合并两个有序链表:(LeetCode题目编号:21)
这一题递归实现 代码十分简洁
可以这么理解我的解法:
先是递归描点(排好序的点【节点】) 然后return是连线的过程

在这里插入图片描述

在这里插入图片描述

			代码如下:
/**
 * Definition for singly-linked list.
 * public class ListNode {
 *     int val;
 *     ListNode next;
 *     ListNode() {

 }
 *     ListNode(int val) { 
            this.val = val;
      }
 *     ListNode(int val, ListNode next) {
            this.val = val; this.next = next; 
      }
 * }
 */
class Solution {
    public  ListNode mergeTwoLists(ListNode l1, ListNode l2){
         if(l1 == null) { return l2; }
        if(l2 == null) { return l1; }
        ListNode ll=l1.val<l2.val? l1:l2;
        if(l1.val>=l2.val){
            ll.next=mergeTwoLists(ll.next,l1);
        }else{
            ll.next=mergeTwoLists(ll.next,l2);
        }
        return ll;
    }

}


总结

你需要掌握

1.熟练的实现链表 信手拈来

2.掌握常见题型的 基本解法 一定要有自己的想法 和理解 即使你看不懂别人写的

3.我为实现的高效率版本 回文链表判断 你可以写完教我 私信我嘻嘻!!

4.谢谢你的观看噢!(学累了吧来看点治愈人心的图片)
在这里插入图片描述

别冲了!保重!

评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值