【链表练习合集Java版】

1、反转链表

题目描述:输入一个链表,反转链表后,输出新链表的表头。

解题方法:递归方法,非递归方法

图解:

链表 5—>4—>3—>2—>1—>null

反转成:1—>2—>3—>4—>5—>null

/*
public class ListNode {
    int val;
    ListNode next = null;

    ListNode(int val) {
        this.val = val;
    }
}*/

//递归写法
public class Solution1 {
    public ListNode ReverseList(ListNode head) {
        if(head == null || head.next == null) return head;
        ListNode newHead = ReverseList(head.next);//逐个反转
        head.next.next = head;//让head下一个结点的next指向head;
        head.next = null;//当前结点指向null;
        return newHead;
    }
}

//非递归写法
public class Solution2 {
    public ListNode ReverseList(ListNode head){
       if(head == null || head.next == null) return head;
        ListNode newHead = null;
        while(head != null){
            ListNode tmp = head.next;//1
            head.next = newHead;//2
            newHead = head;//3
            head = tmp;//4
        }
        return newHead;
    }
}

2、判断链表是否有环

解题思路:快慢指针,有环必然存在指针相等

public boolean hasCycle(ListNode head) {
		if(head == null || head.next == null) return false;
		ListNode slow = head;
		ListNode fast = head.next;
		while(fast != null && fast.next != null) {//重点理解
			if(slow == fast) return true;
			slow = slow.next;
			fast = fast.next.next;
		}
		return false;
	}

3、合并有序链表

public ListNode mergeTwoLists (ListNode l1, ListNode l2) {
        if(l1 == null ) return l2;
        if(l2 == null) return l1;
        if(l1.val <= l2.val){
                l1.next = mergeTwoLists(l1.next,l2);
                return l1;
            }else{
                l2.next = mergeTwoLists(l1,l2.next);
                return l2;
            }
    }

//优化递归
    public ListNode mergeTwoLists(ListNode linked1, ListNode linked2) {
        //只要有一个为空,就返回另一个
        if (linked1 == null || linked2 == null)
            return linked2 == null ? linked1 : linked2;
        //把小的赋值给first
        ListNode first = (linked2.val < linked1.val) ? linked2 : linked1;
        first.next = mergeTwoLists(first.next, first == linked1 ? linked2 : linked1);
        return first;
    }

4、删除链表倒数第n个结点

解题思路:

删除倒数第k个结点,就是删除顺数第(链表长度-n)个结点;

快慢指针法,将快指针设定为第n个结点处,慢指针在第1个结点,当快指针指向尾结点时,此时删掉慢指针指向的结点。

例如:链表1—>2—>3—>4—>5—>6—>7—>null,n=3,删除5这个结点

public ListNode removeNthFromEnd (ListNode head, int n) {
       //利用快慢指针,快指针指向k处,慢指针指向head处,当快指针指向最后一个结点
       if(head == null){return null;}
       ListNode fast = head;
       ListNode slow = head;  
       ListNode prev = null;
         
        for(int i = 1;i < n;i++){//fast先走n-1步
            if(fast.next == null){
                return null;
            }
            fast = fast.next;
        }
//执行后,fast指向3这个结点
        
        while(fast.next != null){
            fast = fast.next;
            prev = slow;//标记删除结点的前一个结点
            slow = slow.next;
        }
//执行后,fast指向7这个结点,prev指向4这个结点,slow指向5这个结点
        if(prev == null){
            head = head.next;
        }else{
            prev.next = prev.next.next;//删除5这个结点
        }
        return head;
    }

5、删除链表中重复节点

题目描述:给出一个升序排序的链表,删除链表中的所有重复出现的元素,只保留原链表中只出现一次的元素。(链表是有序的)

解题思路:创建一个新的节点,同时注意不同连续节点的重复处理。

public ListNode deleteDuplicates (ListNode head) {
    if(head == null || head.next == null){
        return head;
        }
        ListNode root = new ListNode(Integer.MAX_VALUE);
        root.next = head;
        ListNode pre = root;
        ListNode cur = root;
        while(cur != null){
            while(cur.next != null && cur.val == cur.next.val){//找出重复节点
                cur = cur.next;
            }
            cur = cur.next;//判断重复节点的后序节点是否也是重复的
            if(cur != null && cur.next != null && cur.val == cur.next.val){
                continue;//终止当前循环,执行下一次循环
            }
            //没有重复值
                pre.next = cur;
                pre = pre.next;
            }
            return root.next;
        }
}

 

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值