牛客-链表

牛客算法刷题


前言

一、链表

1.反转链表

描述:
给定一个单链表的头结点pHead(该头节点是有值的,比如在下图,它的val是1),长度为n,反转该链表后,返回新链表的表头。
代码如下(示例):

方法一:
public class Solution {
    /**
     * 代码中的类名、方法名、参数名已经指定,请勿修改,直接返回方法规定的值即可
     *
     * 
     * @param head ListNode类 
     * @return ListNode类
     */
    public ListNode ReverseList (ListNode head) {
        // write code here
        ListNode pre =  null;
        ListNode temp = null;
        while(head != null){
            temp = head.next;
            head.next = pre;
            pre = head;
            head = temp;
        }

        return pre;
    }

2.链表内指定区间反转

描述:将一个节点数为 size 链表 m 位置到 n 位置之间的区间反转,要求时间复杂度O(n),空间复杂度O(1)。
代码如下(示例):

public class Solution {
    /**
     * 代码中的类名、方法名、参数名已经指定,请勿修改,直接返回方法规定的值即可
     *
     * 
     * @param head ListNode类 
     * @param m int整型 
     * @param n int整型 
     * @return ListNode类
     */
    public ListNode reverseBetween (ListNode head, int m, int n) {
        // write code here
        ListNode dummy = new ListNode(0);
        dummy.next = head;
        ListNode pre = dummy;
        for(int i = 1; i <m; i++){
            pre = pre.next;
        }

        ListNode cur = pre.next;
        ListNode temp;
        for(int i = m; i < n; i ++){
            temp = cur.next;
            cur.next = temp.next;
            temp.next = pre.next;
            pre.next = temp;
        }
        return dummy.next;
    }

3.合并两个排序的链表

描述:输入两个递增的链表,单个链表的长度为n,合并这两个链表并使新链表中的节点仍然是递增排序的。
代码如下(示例):

方法一:
public class Solution {
    /**
     * 一般解法
     *
     * 
     * @param pHead1 ListNode类 
     * @param pHead2 ListNode类 
     * @return ListNode类
     */
    public ListNode Merge (ListNode pHead1, ListNode pHead2) {
        // write code here
        if(pHead1 ==null){
            return pHead2;
        }
        if(pHead2 == null){
            return pHead1;
        }
        ListNode dummy = new ListNode(0);
        ListNode list = dummy;
        while(pHead1 != null && pHead2 != null){
            if(pHead1.val >= pHead2.val){
                list.next = pHead2;
                pHead2 = pHead2.next;
            }else if(pHead1.val < pHead2.val){
                list.next = pHead1;
                pHead1 = pHead1.next;
            }
            list = list.next;
        }
        if(pHead1 == null){
            list.next = pHead2;
        }
        if(pHead2 == null){
            list.next = pHead1;
        }
        return dummy.next;

    }
方法二:
public class Solution {
    /**
     * 递归法
     *
     * 
     * @param pHead1 ListNode类 
     * @param pHead2 ListNode类 
     * @return ListNode类
     */
    public ListNode Merge (ListNode pHead1, ListNode pHead2) {
        // write code here
        if(pHead1 ==null){
            return pHead2;
        }
        if(pHead2 == null){
            return pHead1;
        }
        ListNode list = null;
        if(pHead1.val >= pHead2.val){
                list = pHead2;
                list.next = Merge(pHead1,pHead2.next);
        }else if(pHead1.val < pHead2.val){
                list = pHead1;
                list.next = Merge(pHead1.next,pHead2);
        }
        return list;
    }

4.判断链表中是否有环

描述:判断给定的链表中是否有环。如果有环则返回true,否则返回false。
代码如下(示例):

public class Solution {
    public boolean hasCycle(ListNode head) {
        if(head == null){
            return false;
        }
        ListNode fast = head;
        ListNode slow = head;
        while(slow.next != null && fast.next != null && fast.next.next != null){
            fast = fast.next.next;
            slow = slow.next;
            if(fast== slow){
                return true;
            }
        }
        return false;
    }

4.链表中环的入口结点

描述:给一个长度为n链表,若其中包含环,请找出该链表的环的入口结点,否则,返回null。
代码如下(示例):

方法一:
public class Solution {
    public ListNode EntryNodeOfLoop(ListNode pHead) {
        if(pHead == null){
            return null;
        }
        ListNode fast = pHead;
        ListNode slow = pHead;
        while(fast.next != null && fast.next.next != null){
            fast = fast.next.next;
            slow = slow.next;
            if(fast == slow){
                slow = pHead;
                while(slow != fast){
                    slow = slow.next;
                    fast = fast.next;
        }
        return slow;
            }
        }
        return null;
    }
方法二:
public class Solution {

    public ListNode EntryNodeOfLoop(ListNode pHead) {
        // ArrayList<ListNode> listNodes = new ArrayList<>();
        // HashMap<ListNode,Boolean> Map = new HashMap<>();
         HashSet<ListNode> set = new HashSet<>();
         while(pHead != null){
            if(set.contains(pHead)){
                return pHead;
            }
            set.add(pHead);
            pHead = pHead.next;
         }
         return null;
    }

5.链表中倒数最后k个结点

描述:输入一个长度为 n 的链表,设链表中的元素的值为 ai ,返回该链表中倒数第k个节点。
如果该链表长度小于k,请返回一个长度为 0 的链表。
代码如下(示例):

方法一:
public class Solution {
    /**
     * 代码中的类名、方法名、参数名已经指定,请勿修改,直接返回方法规定的值即可
     *
     * 
     * @param pHead ListNode类 
     * @param k int整型 
     * @return ListNode类
     */
    public ListNode FindKthToTail (ListNode pHead, int k) {
        // write code here
        if(pHead == null){
            return null;
        }
        ListNode fast = pHead;
        while(fast != null && k > 0 ){
            fast = fast.next;
            k = k-1;
        }
        if(k > 0){
            return null;
        }
        ListNode slow = pHead;
        while(fast != null){
            slow = slow.next;
            fast = fast.next;
        }
        return slow;
    }
方法二:
public class Solution {
    /**
     * 代码中的类名、方法名、参数名已经指定,请勿修改,直接返回方法规定的值即可
     * @param pHead ListNode类 
     * @param k int整型 
     * @return ListNode类
     */
    public ListNode FindKthToTail (ListNode pHead, int k) {
        // write code here
        if(pHead == null){
            return null;
        }
        ListNode fast = pHead;
        int i = 0;
        while(fast != null){
            fast = fast.next;
            i = i+1;
        }
        if(i-k < 0){
            return null;
        }
        ListNode slow = pHead;
        for(int j = 0; j < i-k; j++){
            slow = slow.next;
        }
        return slow;
    }

6.两个链表的第一个公共结点

描述:输入两个无环的单向链表,找出它们的第一个公共结点,如果没有公共节点则返回空。
例如,输入{1,2,3},{4,5},{6,7}时,两个无环的单向链表的结构如下图所示:可以看到它们的第一个公共结点的结点值为6,所以返回结点值为6的结点。
在这里插入图片描述

代码如下(示例):
使用两个指针N1,N2,一个从链表1的头节点开始遍历,我们记为N1,一个从链表2的头节点开始遍历,我们记为N2。
让N1和N2一起遍历,当N1先走完链表1的尽头(为null)的时候,则从链表2的头节点继续遍历,同样,如果N2先走完了链表2的尽头,则从链表1的头节点继续遍历,也就是说,N1和N2都会遍历链表1和链表2。
因为两个指针,同样的速度,走完同样长度(链表1+链表2),不管两条链表有无相同节点,都能够到达同时到达终点。
在这里插入图片描述

public class Solution {
    public ListNode FindFirstCommonNode(ListNode pHead1, ListNode pHead2) {
        if(pHead1 == null || pHead2 == null){
            return null;
        }
        ListNode p1 = pHead1;
        ListNode p2 = pHead2;
        while(p1 != p2){
            p1 = (p1 == null ? pHead2 : p1.next);
            p2 = (p2 == null ? pHead1 : p2.next);
        }
        return p1;
    }

7.链表相加(二)

描述:假设链表中每一个节点的值都在 0 - 9 之间,那么链表整体就可以代表一个整数。给定两个这种链表,请生成代表两个整数相加值的结果链表。
例如:链表 1 为 9->3->7,链表 2 为 6->3,最后生成新的结果链表为 1->0->0->0。
在这里插入图片描述
代码如下(示例):

public class Solution {
    /**
     * 代码中的类名、方法名、参数名已经指定,请勿修改,直接返回方法规定的值即可
     *
     * 
     * @param head1 ListNode类 
     * @param head2 ListNode类 
     * @return ListNode类
     */
    public ListNode addInList (ListNode head1, ListNode head2) {
        // write code here
        ListNode list1 = getReturnList(head1);
        ListNode list2 = getReturnList(head2);
        int n = 0;
        ListNode result = new ListNode(-1);
        ListNode pre = result;
        while(list1 != null || list2 != null || n != 0){
            if(list1 != null){
                n = n + list1.val;
                list1 = list1.next; 
            }
            if(list2 != null){
                n = n + list2.val;
                list2 = list2.next;
            }
            //取余
            pre.next = new ListNode(n % 10);
            //指针移位
            pre = pre.next;
            //取整进位
            n = n / 10;
        }
        return getReturnList(result.next);
    }
	//反转链表
    private ListNode getReturnList(ListNode node){
        if(node == null || node.next == null){
            return node;
        }
        ListNode pre = null, temp;
        while(node != null){
            temp = node.next;
            node.next = pre;
            pre = node;
            node = temp;
        }
        return pre;
    }

8.单链表的排序

描述:给定一个节点数为n的无序单链表,对其按升序排序。
代码如下(示例):

public class Solution {
    /**
     * 代码中的类名、方法名、参数名已经指定,请勿修改,直接返回方法规定的值即可
     * @param head ListNode类 the head node
     * @return ListNode类
     */
    public ListNode sortInList (ListNode head) {
        // write code here
        ArrayList<Integer> list = new ArrayList();
        while(head != null){
            list.add(head.val);
            head = head.next;
        }
        Collections.sort(list);
        ListNode root = new ListNode(0);
        ListNode cur = root;
        for (int i = 0; i < list.size(); i++){
            cur.next = new ListNode(list.get(i));
            cur = cur.next;
        }
    return root.next;
    }

9.单链表的排序

描述:给定一个链表,请判断该链表是否为回文结构。回文是指该字符串正序逆序完全一致。
代码如下(示例):

方法一:
public class Solution {
    /**
     * 利用堆栈法
     * @param head ListNode类 the head
     * @return bool布尔型
     */
    public boolean isPail (ListNode head) {
        // write code here
        Stack<ListNode> stack = new Stack<>();
        ListNode node = head;
        while(node != null){
            stack.push(node);
            node = node.next;
        }
        while(head != null){
            if(head.val != stack.pop().val){
                return false;
            }
            head = head.next;
        }
    return true;
    }
方法二:
public class Solution {
    /**
     * 利用双指针法
     * @param head ListNode类 the head
     * @return bool布尔型
     */
    public boolean isPail (ListNode head) {
        // write code here
        if(head == null || head.next == null){
            return true;
        }
        ListNode slow = head, fast = head;
        while (fast.next != null && fast.next.next != null){
            slow = slow.next;
            fast = fast.next.next;
        }
        ListNode mid = getReturnList(slow.next);
        while(mid != null && head != null){
            if(head.val != mid.val){
            return false;
            }
            head = head.next;
            mid = mid.next;
        }
        return true;
    }
    private ListNode getReturnList(ListNode list){
        if(list == null || list.next == null)
            return list;
        ListNode pre = null,temp;
        while(list != null){
            temp = list.next;
            list.next = pre;
            pre = list;
            list = temp;
        }
        return pre;
    }

10.链表的奇偶重排

描述:给定一个单链表,请设定一个函数,将链表的奇数位节点和偶数位节点分别放在一起,重排后输出。注意是节点的编号而非节点的数值。

代码如下(示例):

public class Solution {
    /**
     * 代码中的类名、方法名、参数名已经指定,请勿修改,直接返回方法规定的值即可
     * @param head ListNode类 
     * @return ListNode类
     */
    public ListNode oddEvenList (ListNode head) {
        // write code here
        if(head == null || head.next == null){
            return head;
        }
        ListNode list1 = head, list2 = head.next, list2Head = list2;
        while(list2 != null && list2.next != null){
            list1.next = list2.next;
            list1 = list1.next;
            list2.next = list1.next;
            list2 = list2.next;
        }
        list1.next = list2Head;
        return head;
    }

11.删除有序链表中重复的元素-I

描述:删除给出链表中的重复元素(链表中元素从小到大有序),使链表中的所有元素都只出现一次.
代码如下(示例):

方法一:
public class Solution {
    /**
     * @param head ListNode类 
     * @return ListNode类
     */
    public ListNode deleteDuplicates (ListNode head) {
        // write code here
        if(head == null || head.next == null){
            return head;
        }
        ListNode pre = head;
        while (pre != null && pre.next != null){
            if(pre.val == pre.next.val){
                pre.next = pre.next.next;
            }else{
                pre = pre.next;
            }
        }
        return head;
    }

12.删除有序链表中重复的元素-I

描述:给出一个升序排序的链表,删除链表中的所有重复出现的元素,只保留原链表中只出现一次的元素。
代码如下(示例):

public class Solution {
    /**
     * 代码中的类名、方法名、参数名已经指定,请勿修改,直接返回方法规定的值即可
     *
     *
     * @param head ListNode类
     * @return ListNode类
     */
    public ListNode deleteDuplicates (ListNode head) {
        // write code here
        ListNode newList = new ListNode(-1);
        newList.next = head;
        ListNode pre = newList;
        while (pre.next != null && pre.next.next != null) {
            int val = pre.next.next.val;
            if(pre.next.val == val){
                while(pre.next != null && pre.next.val == val){
                    pre.next = pre.next.next;
                }
            }else{
                pre = pre.next;
            }
        }
        return newList.next;
    }

总结

坚持每天刷题!!!(打卡第2天)

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值