LeeCode链表习题训练合集

Leetcode 21. 合并两个有序链表

将两个升序链表合并为一个新的升序链表并返回。新链表时通过拼接给定的两个链表的所有节点组成的。

示例
在这里插入图片描述

/**
 * 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) {
        ListNode l3 = new ListNode(-1);		//创建一个表头用来存储合并之后的链表
        ListNode p = l3;		//定义一个指针指向新链表的表头
        while(l1!=null&&l2!=null)	//循环遍历两个旧链表
        {
        	//两个链表中的结点相比较,将数据较小的结点存入新链表中
            if(l1.val >= l2.val)	
            {
                  p.next = l2;
                  l2 = l2.next;
            }
            else
            {
                p.next = l1;
                l1 = l1.next;
            }
            p = p.next; 
        }
        p.next = l1 == null ? l2 : l1;		//两个旧链表中肯定有一个率先遍历完,这时只需要将另一个链表中所有结点顺序存入新链表中就可以了
        return l3.next;		//这里的next是因为在初始化新链表时首元结点赋值为-1,我们不需要这个首元结点
    }
}
leetcode 83. 删除排序链表中的重复元素

给定一个排序链表,删除所有的重复元素,使得每个元素只出现一次。
在这里插入图片描述

/**
 * Definition for singly-linked list.
 * public class ListNode {
 *     int val;
 *     ListNode next;
 *     ListNode(int x) { val = x; }
 * }
 */
class Solution {
    public ListNode deleteDuplicates(ListNode head) {
        ListNode p = head;		//创建一个临时指针用来操作
        while(p != null && p.next!=null)	//遍历链表,当一个结点与它之后的一个结点不为空时
        {
            if(p.val == p.next.val)		//如果连续两个结点的值相等
            {
                p.next = p.next.next;	//删除相等结点
            }
            else
            p = p.next;
        }
        return head;		//返回头指针地址
    }
}
Leetcode 141.环形链表

给定一个链表,判断链表中是否有环。

如果链表中有某个节点,可以通过连续跟踪 next 指针再次到达,则链表中存在环。 为了表示给定链表中的环,我们使用整数 pos 来表示链表尾连接到链表中的位置(索引从 0 开始)。 如果 pos 是 -1,则在该链表中没有环。注意:pos 不作为参数进行传递,仅仅是为了标识链表的实际情况。

如果链表中存在环,则返回 true 。 否则,返回 false 。

在这里插入图片描述

/**
 * Definition for singly-linked list.
 * class ListNode {
 *     int val;
 *     ListNode next;
 *     ListNode(int x) {
 *         val = x;
 *         next = null;
 *     }
 * }
 */
public class Solution {
    public boolean hasCycle(ListNode head) {
    	//用一个Set集合来存储节点数据
        Set<ListNode> set = new HashSet<>();
        while(head != null){
        	//在遍历节点的过程中,如果集合中已经存在这个节点,就说明有环,返回true
            if(set.contains(head))
            return true;
            else
            //如果没有,则将其添加进集合中
            set.add(head);
            head = head.next;
        }
        return false;
    }
}
//我们再来用双指针来解这道题
public class Solution{
	public boolean hasCycle(ListNode head){
		//当只有头节点或没有节点时,返回false
		if (head == null || head.next == null)
		return false;
		//定义快慢两个指针
		ListNode slow = head;
		ListNode fast = head.next;
		//遍历链表时如果快指针为空则没有环,否则快慢指针你一定会相遇,则证明有环存在
		while(slow != fast){
			if(fast==null || fast.next==null)
			return false;
			slow = slow.next;
			fast = fast.next.next;
		}
		return true;
	}
}
Leetcode 160. 相交链表

编写一个程序,找到两个单链表相交的起始节点。

如下面的两个链表:

在这里插入图片描述

在节点 c1 开始相交。

/**
 * 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;
        ListNode pa = headA;
        ListNode pb = headB;
        while(pa != pb){
            pa = pa != null ? pa.next : headB;
            pb = pb != null ? pb.next : headA;
        }
        return pa;
    }  
}

这道题可以采用双指针的方法来解决。虽然两个链表长度不相等,但是两个链表长度的和是相等的。当遍历链表A时,如果结束则返回链表B的头节点;遍历链表B时,如果结束则返回链表A的头节点。假如两个链表相交,则一定在末尾的一段是一样的,所以就一定会同时到达交点。而如果没有相交,则两个链表同时到达末尾。

Leetcode 203.移除链表元素

删除链表中等于给定值 val 的所有节点。
在这里插入图片描述

/**
 * Definition for singly-linked list.
 * public class ListNode {
 *     int val;
 *     ListNode next;
 *     ListNode(int x) { val = x; }
 * }
 */
class Solution {
    public ListNode removeElements(ListNode head, int val) {
    	//设置一个虚拟头节点
        ListNode ph = new ListNode(-1);
        ph.next = head;
        //设置一个指针用来遍历整个链表
        ListNode p = ph;
        //遇到相等的值就删掉,否则继续遍历
        while(p.next!=null){
            if(p.next.val == val){
                p.next = p.next.next;
            }
            else
            p = p.next;
        } 
        //因为头结点赋值为-1,所以返回ph.next
        return ph.next;
    }
}
LeetCode 206.反转链表

反转一个单链表。
在这里插入图片描述

运用迭代法
/**
 * Definition for singly-linked list.
 * public class ListNode {
 *     int val;
 *     ListNode next;
 *     ListNode(int x) { val = x; }
 * }
 */
class Solution {
    public ListNode reverseList(ListNode head) {
        ListNode curr = head;	//定义指向当前结点的指针
        ListNode prev = null;	//定义一个空指针指向当前结点的前一个结点
        while(curr != null){
            ListNode temp = curr.next;	//当前结点的后一个结点
            curr.next = prev;	//当前结点指向前一个结点
            prev = curr;	//这两步是指针移动,前一个结点和当前结点都往后移动一位
            curr = temp;
        }
        return prev;	//返回新的头引用
    }
}
运用递归法
class Solution {
    public ListNode reverseList(ListNode head) {
    	//	递归结束条件
        if(head==null || head.next==null)
        return head;
        ListNode p = reverseList(head.next);
        //当前指针要指向前一个结点
        head.next.next = head;
        //将原来的指向下一个结点的指针删除,否则会造成循环
        head.next = null;
        return p;
    }
}
LeetCode 234.回文链表

请判断一个链表是否为回文链表。

在这里插入图片描述

/**
 * Definition for singly-linked list.
 * public class ListNode {
 *     int val;
 *     ListNode next;
 *     ListNode(int x) { val = x; }
 * }
 */
class Solution {
    public boolean isPalindrome(ListNode head) {
    	//维护一个对象类型的数组
        List<Integer> arrs = new ArrayList<>();
        ListNode p = head;
        //将链表中的数据装进数组中
        while(p != null){
            arrs.add(p.val);
            p = p.next;
        }
        //定义两个指针,一头一尾
        int begin = 0;
        int end = arrs.size()-1;
        //遍历整个数组,当两个指针所指向的数据不相等时则不是回文链表
        while(begin<end){
            if(!arrs.get(begin).equals(arrs.get(end)))
            return false;
            begin++;
            end--;
        }
        return true;
    }
}
/**
 * Definition for singly-linked list.
 * public class ListNode {
 *     int val;
 *     ListNode next;
 *     ListNode(int x) { val = x; }
 * }
 */
class Solution {
    public boolean isPalindrome(ListNode head) {
        if(head == null)
        return true;
        //寻找中间结点
        ListNode firstHalfEnd = findmid(head);
        //反转前半部分链表
        ListNode secondHalfStart = reverse(firstHalfEnd.next);
        //将链表后半段进行反转之后,比较两部分链表的值,如果都相等则是回文链表
        ListNode p1 = head;
        ListNode p2 = secondHalfStart;
        while(p2 != null){
            if(p1.val != p2.val)
            return false;
            p1 = p1.next;
            p2 = p2.next;
        }
        //最后要将反转的后半段再恢复原样
        firstHalfEnd.next = reverse(secondHalfStart);
        return true;   
    }

	//定义寻找中间结点的函数
    private ListNode findmid(ListNode head){
    ListNode fast = head;
        ListNode slow = head;
        while(fast.next!=null && fast.next.next!=null){
            fast = fast.next.next;
            slow = slow.next;
        }
        return slow;
    }
	
	//定义反转链表函数
    private ListNode reverse(ListNode head){
    ListNode prev = null;
    ListNode curr = head;
    while(curr != null){
        ListNode temp = curr.next;
        curr.next = prev;
        prev = curr;
        curr = temp;
    }
    return prev;
    }

}






LeetCode 237.删除链表中的结点

请编写一个函数,使其可以删除某个链表中给定的(非末尾)节点。传入函数的唯一参数为 要被删除的节点 。

现有一个链表 – head = [4,5,1,9],它可以表示为:

在这里插入图片描述

在这里插入图片描述

/**
 * Definition for singly-linked list.
 * public class ListNode {
 *     int val;
 *     ListNode next;
 *     ListNode(int x) { val = x; }
 * }
 */
 //思路就是把要删除的结点的值赋给下一个结点的值,然后再删除这个结点就可以了。
class Solution {
    public void deleteNode(ListNode node) {
        node.val = node.next.val;
        node.next = node.next.next;
    }
}
LeetCode 876.链表的中间节点

给定一个带有头结点head的非空单链表,返回链表的 中间结点。
如果由两个中间结点,则返回第二个中间节点。

在这里插入图片描述

/**
 * Definition for singly-linked list.
 * public class ListNode {
 *     int val;
 *     ListNode next;
 *     ListNode(int x) { val = x; }
 * }
 */
class Solution {
	//整体思路就是用快慢双指针遍历链表,当快指针遍历到最后一个链表的时候,慢指针正好遍历到中间节点
    public ListNode middleNode(ListNode head) {
        ListNode slow = head;	//建立慢指针
        ListNode fast = head;	//建立快指针
        while(fast!=null &&fast.next!=null){
            slow = slow.next;
            fast = fast.next.next;
        }
        return slow;
    }
}
LeetCode 1290.二进制链表转整数

给你一个单链表的引用结点head。链表中每个结点的值不是0就是1.已知此链表是一个整数数字的二进制表示形式。
请你返回该链表所表示数字的十进制值。

在这里插入图片描述
在这里插入图片描述

/**
 * Definition for singly-linked list.
 * public class ListNode {
 *     int val;
 *     ListNode next;
 *     ListNode(int x) { val = x; }
 * }
 */
 //就是简单的二进制转十进制的方法
class Solution {
    public int getDecimalValue(ListNode head) {
        ListNode p = head;
        int ans = 0;
        while(p != null){
            ans = ans*2 + p.val;
            p = p.next;
        }
        return ans;
    }
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值