链表

47 阅读3分钟

001 反转链表

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

输入: {1,2,3}

返回值:{3,2,1}

public class Solution {
    public ListNode ReverseList(ListNode head) {
        ListNode newHead = null;
        while(head != null){
            ListNode next = head.next;
            head.next = newHead;
            newHead = head;
            head = next;
        }
        return newHead;
    }
}

002 链表内指定区间反转

将一个节点数为 size 链表 m 位置到 n 位置之间的区间反转。

输入:{1,2,3,4,5},2,4

返回值:{1,4,3,2,5}

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
        if(head == null){
            return null;
        }
        if(m == n) {
            return head;
        }
        //添加辅助头节点
        ListNode newHead = new ListNode(-1);
        newHead.next = head;

        ListNode p = newHead;
        ListNode a, b, c, d;
        for(int i=0; i<m-1; i++){
            p = p.next;
        }
        a = p;
        b = p.next;
        for(int i=0; i<(n-m+1); i++){
            p = p.next;
        }
        c = p;
        d = p.next;
        //断开cd 
        c.next = null;
        //反转b
        reverseList(b);
        //连接 ac bd
        a.next = c;
        b.next = d;
        return newHead.next;
    }

    public ListNode reverseList(ListNode head){
        ListNode newHead = null;
        while(head != null){
            ListNode next = head.next;
            head.next = newHead;
            newHead = head;
            head = next;
        }
        return newHead;
    }
}

003 链表中的节点每k个一组翻转

将给出的链表中的节点每 k 个一组翻转,返回翻转后的链表,如果链表中的节点数不是 k 的倍数,将最后剩下的节点保持原样,你不能更改节点中的值,只能更改节点本身。

输入:{1,2,3,4,5},2

返回值:{2,1,4,3,5}

解题思路:先求出所有区间值,然后结合 002 链表内指定区间反转解题。

public class Solution {
    /**
     *
     * @param head ListNode类
     * @param k int整型
     * @return ListNode类
     */
    public ListNode reverseKGroup (ListNode head, int k) {
        // write code here
        if(head == null || k == 1){
            return head;
        }
        int c = 0;
        ListNode  p = head;
        while(p != null){
            p = p.next;
            c++;
        }
        int m = c/k;
        for(int i=1; i<=m; i++){
           head = reverseBetween(head,(i-1)*k + 1, i*k);
        }
        // if(m*k < c){
        //     head = reverseBetween(head,m*k + 1, c);
        // }
        return head;

    }

    public ListNode reverseBetween (ListNode head, int m, int n) {
        // write code here
        if (head == null) {
            return null;
        }
        if (m == n) {
            return head;
        }
        //添加辅助头节点
        ListNode newHead = new ListNode(-1);
        newHead.next = head;

        ListNode p = newHead;
        ListNode a, b, c, d;
        for (int i = 0; i < m - 1; i++) {
            p = p.next;
        }
        a = p;
        b = p.next;
        for (int i = 0; i < (n - m + 1); i++) {
            p = p.next;
        }
        c = p;
        d = p.next;
        //断开cd
        c.next = null;
        //反转b
        reverseList(b);
        //连接 ac bd
        a.next = c;
        b.next = d;
        return newHead.next;
    }

    public ListNode reverseList(ListNode head) {
        ListNode newHead = null;
        while (head != null) {
            ListNode next = head.next;
            head.next = newHead;
            newHead = head;
            head = next;
        }
        return newHead;
    }
}

004 合并两个排序的链表

输入两个递增的链表,单个链表的长度为n,合并这两个链表并使新链表中的节点仍然是递增排序的。

输入:{1,3,5},{2,4,6}

返回值:{1,2,3,4,5,6}

public class Solution {
    public ListNode Merge(ListNode list1,ListNode list2) {
        ListNode newHead = new ListNode(-1);
        ListNode p =newHead;
        while(list1 != null && list2 !=null){
            if(list1.val <= list2.val){
                p.next = list1;
                list1 = list1.next;
            } else {
                p.next = list2;
                list2 = list2.next;
            }
            p = p.next;
        }
        if(list1 != null){
            p.next = list1;
        }
        if(list2 != null){
            p.next = list2;
        }
        return newHead.next;
    }
}

005 合并k个已排序的链表

合并 k 个升序的链表并将结果作为一个升序的链表返回其头节点。

输入:[{1,2,3},{4,5,6,7}]

返回值:{1,2,3,4,5,6,7}

public class Solution {
    public ListNode mergeKLists(ArrayList<ListNode> lists) {
        if(lists.size() == 0){
            return null;
        }
        if(lists.size() == 1){
            return lists.get(0);
        }
        ListNode newListNode = lists.get(0);
        for(int i=1; i<lists.size(); i++){
            newListNode = Merge(newListNode, lists.get(i));
        }
        return newListNode;
    }
    public ListNode Merge(ListNode list1, ListNode list2) {
        ListNode newHead = new ListNode(-1);
        ListNode p = newHead;
        while (list1 != null && list2 != null) {
            if (list1.val <= list2.val) {
                p.next = list1;
                list1 = list1.next;
            } else {
                p.next = list2;
                list2 = list2.next;
            }
            p = p.next;
        }
        if (list1 != null) {
            p.next = list1;
        }
        if (list2 != null) {
            p.next = list2;
        }
        return newHead.next;
    }
}

006 判断链表中是否有环

判断给定的链表中是否有环。如果有环则返回true,否则返回false。

输入:{3,2,0,-4},1

返回值:true

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

007 链表中倒数最后k个结点

输入一个长度为 n 的链表,设链表中的元素的值为 ai ,返回该链表中倒数第k个节点。

如果该链表长度小于k,请返回一个长度为 0 的链表。

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

008 删除链表的倒数第n个节点

给定一个链表,删除链表的倒数第 n 个节点并返回链表的头指针

输入:{1,2},2

返回值:{2}

public class Solution {
    /**
     * 
     * @param head ListNode类 
     * @param n int整型 
     * @return ListNode类
     */
    public ListNode removeNthFromEnd (ListNode head, int n) {
        // write code here
        ListNode newHead = new ListNode(-1);
        newHead.next = head;

        ListNode p1 = newHead;
        ListNode p2 = newHead;

        for(int i=1; i<=n; i++){
            p1 = p1.next;
        }

        while(p1.next != null){
            p1 = p1.next;
            p2 = p2.next;
        }
        p2.next = p2.next.next;
        return newHead.next;
    }
}

009 两个链表的第一个公共结点

输入两个无环的单向链表,找出它们的第一个公共结点,如果没有公共节点则返回空。(注意因为传入数据是链表,所以错误测试数据的提示是用其他方式显示的,保证传入数据是正确的)

输入:{1,2,3},{4,5},{6,7}

返回值:{6,7}

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

010 链表相加

假设链表中每一个节点的值都在 0 - 9 之间,那么链表整体就可以代表一个整数。

给定两个这种链表,请生成代表两个整数相加值的结果链表。

输入:[9,3,7],[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 newHead = new ListNode(-1);
        //反转
        head1 = reverseList(head1);
        head2 = reverseList(head2);
        ListNode p = newHead;
        int c = 0;//进位
        while(head1 != null  || head2 != null){
            int m =0 ,n = 0;
            if(head1 != null){
                m = head1.val;
                head1 = head1.next;
            }
            if(head2 != null){
                n = head2.val;
                head2 = head2.next;
            }
            int sum = m + n + c;
            c = sum>=10?1:0;
            ListNode t = new ListNode(sum%10);
            p.next = t;
            p = p.next;
        }
        if(c == 1){
           ListNode t = new ListNode(1);
            p.next = t;
        }
        // 反转
        newHead = reverseList(newHead.next);
        return newHead;
    }

    public ListNode reverseList(ListNode head){
        ListNode newHead = null;
        while(head != null){
            ListNode next = head.next;
            head.next = newHead;
            newHead = head;
            head = next;
        }
        return newHead;
    }
}

011 判断一个链表是否为回文结构

给定一个链表,请判断该链表是否为回文结构。

回文是指该字符串正序逆序完全一致。

输入:{1,2,2,1}

返回值:true

public class Solution {
    /**
     *
     * @param head ListNode类 the head
     * @return bool布尔型
     */
    public boolean isPail (ListNode head) {
        // write code here
        // 双指针
        ListNode p1 = head, p2 = head;
        while (p1 != null && p1.next != null) {
            p1 = p1.next.next;
            p2 = p2.next;
        }
        //反转p2
        p2 = reverseList(p2);
        p1 = head;
        while(p2 != null){
            if(p1.val != p2.val){
                return false;
            }
            p1 = p1.next;
            p2 = p2.next;
        }
        return true;
    }
    public ListNode reverseList(ListNode head) {
        ListNode newHead = null;
        while (head != null) {
            ListNode next = head.next;
            head.next = newHead;
            newHead = head;
            head = next;
        }
        return newHead;
    }
}

0012 链表的奇偶重排

给定一个单链表,请设定一个函数,将链表的奇数位节点和偶数位节点分别放在一起,重排后输出。

注意是节点的编号而非节点的数值。

输入:{1,2,3,4,5,6}

返回值:{1,3,5,2,4,6}

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

0013 删除有序链表中重复的元素**-I**

删除给出链表中的重复元素(链表中元素从小到大有序),使链表中的所有元素都只出现一次。

输入:{1,1,2}

返回值:{1,2}

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 p = head;
        while(p.next != null){
            if(p.val == p.next.val){
                p.next = p.next.next;
            } else {
                p = p.next;
            }
        }
        return head;
    }
}

0014 删除有序链表中重复的元素-II

给出一个升序排序的链表,删除链表中的所有重复出现的元素,只保留原链表中只出现一次的元素。

输入:{1,2,2}

返回值:{1}

public class Solution {
    /**
     * 
     * @param head ListNode类 
     * @return ListNode类
     */
    public ListNode deleteDuplicates (ListNode head) {
        // write code here
        // 添加辅助节点
        ListNode newHead = new ListNode(-1);
        newHead.next = head;
        ListNode p = newHead;
        while(p.next!=null && p.next.next!=null){
            if(p.next.val == p.next.next.val){
                int m = p.next.val;
                while(p.next != null && p.next .val == m){
                    p.next = p.next.next;
                }
            } else {
                p = p.next;
            }
        }
        return newHead.next;
    }
}