【java】链表习题

链表习题

1. 逆置链表

/**
 * 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 result=null;
        ListNode cur=head;
        while(cur!=null)
        {
            ListNode next=cur.next;
            cur.next=result;
            result=cur;
            cur=next;
        }
        return result;
    }
}

2. 删除链表中重复的结点
在一个排序的链表中,存在重复的结点,请删除该链表中重复的结点,重复的结点不保留,返回链表头指针。
例如,链表1->2->3->3->4->4->5 处理后为 1->2->5

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

    ListNode(int val) 
    {
        this.val = val;
    }
}
*/
public class Solution 
{
    public ListNode deleteDuplication(ListNode pHead)
    {
         if (pHead == null) 
         {
            return null;
         }
         ListNode prev = null;
         ListNode p1 = pHead;
         ListNode p2 = pHead.next;    
         while (p2 != null) 
         {
            if (p1.val != p2.val) 
            {
                prev = p1;
                p1 = p2;
                p2 = p2.next;
            } 
            else 
            {
                while (p2 != null && p2.val == p1.val) 
                {
                    p2 = p2.next;
                }
                
                if (prev == null) 
                {
                    pHead = p2;
                } 
                else 
                {
                    prev.next = p2;
                }
                p1 = p2;
                if (p2 != null) 
                {
                    p2 = p2.next;
                }
            }
        }     
        return pHead;  
    }
}

3. 删除链表中等于给定值 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 cur=head;
        ListNode result=null;
        ListNode prev=null;
        while(cur!=null)
        {
            ListNode next=cur.next;
            if(cur.val==val)
            {
                if(cur==head)
                {
                    head=cur.next;
                }
                else
                {
                    prev.next=cur.next;
                }
            }
            else
            {
                prev=cur;
            }
            cur=cur.next;
        }
    return head;
    }
}
//法二
class Solution 
{
    public ListNode removeElements(ListNode head, int val) 
    {
        ListNode tmpHead = new ListNode(-1);
        tmpHead.next = head;
        ListNode prev = tmpHead;
        ListNode cur = head;
        
        while (cur != null) 
        {
            if (cur.val == val) 
            {
                prev.next = cur.next;
            } 
            else 
            {
                prev = cur;
            }
            cur = cur.next;
        }
        return tmpHead.next;
    }
}

4. 复杂链表的复制

/*
// Definition for a Node.
class Node 
{
    int val;
    Node next;
    Node random;

    public Node(int val) 
    {
        this.val = val;
        this.next = null;
        this.random = null;
    }
}
*/
class Solution 
{
    public Node copyRandomList(Node head) 
    {
        if(head==null)
        {
            return null;
        }
        Node p1=head;
        while(p1!=null)
        {
            Node p2=new Node(p1.val);
            p2.random=null;
            p2.next=p1.next;
            p1.next=p2;
            p1=p2.next;
        }
        p1=head;
        while(p1!=null)
        {
            if(p1.random!=null)
            p1.next.random=p1.random.next;
            p1=p1.next.next;
        }
        p1=head;
        Node newHead=head.next;
        while(p1.next!=null)
        {
            Node p2=p1.next;
            p1.next=p1.next.next;
            p1=p2;
        }
        return  newHead; 
    }
}

5. 相交链表
输入两个链表,找到两个单链表相交的起始点

//方法一:长度差判断
public class Solution 
{
    private int getLength(ListNode head) 
    {
        int len = 0;
        for (ListNode c = head; c != null; c = c.next) 
        {
            len++;
        }
        return len;
    }
    public ListNode getIntersectionNode(ListNode headA, ListNode headB) 
    {
        int lenA = getLength(headA);
        int lenB = getLength(headB);
        
        ListNode longer = headA;
        ListNode shorter = headB;
        int diff = lenA - lenB;
        if (lenA < lenB) 
        {
            longer = headB;
            shorter = headA;
            diff = lenB - lenA;
        }
        for (int i = 0; i < diff; i++) 
        {
            longer = longer.next;
        }
        while (longer != shorter) 
        {
            longer = longer.next;
            shorter = shorter.next;
        }
        return longer;
    }
}
//方法二:快慢指针
public class Solution 
{
    public ListNode getIntersectionNode(ListNode headA, ListNode headB) 
	{
        if (headA == null || headB == null) 
        {
            return null;
        }
        ListNode last = headB;
        while (last.next != null) 
        {
            last = last.next;
        }
        last.next = headB;

        ListNode fast = headA;
        ListNode slow = headA;

        while (fast != null && fast.next != null) 
        {
            slow = slow.next;
            fast = fast.next.next;
            if (slow == fast) 
            {
                slow = headA;
                while (slow != fast) 
                {
                    slow = slow.next;
                    fast = fast.next;
                }
                last.next = null;
                return fast;
            }
        }
        last.next = null;
        return 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;
        }
        ListNode pA=headA,pB=headB;
        //第一轮交换表头,抹掉长度差
        //第二轮有交点则相遇
        while(pA!=pB)
        {
            pA=pA==null?headB:pA.next;
            pB=pB==null?headA:pB.next;
        }
        return pA;
    }
}

6. 合并两个有序链表

Node merge(Node head1, Node head2) 
{
        if (head1 == null) 
        {
            return head2;
        }

        if (head2 == null) 
        {
            return head1;
        }

        Node result = null;
        Node last = null;

        Node cur1 = head1;
        Node cur2 = head2;

        while (cur1 != null && cur2 != null) 
        {
            if (cur1.val <= cur2.val) 
            {
                if (result == null) 
                {
                    result = cur1;
                } 
                else 
                {
                    last.next = cur1;
                }
                last = cur1;
                cur1 = cur1.next;
            } 
            else 
            {
                if (result == null) 
                {
                    result = cur2;
                } 
                else 
                {
                    last.next = cur2;
                }
                last = cur2;
                cur2 = cur2.next;
            }
        }

        if (cur1 != null) 
        {
            last.next = cur1;
        } else 
        {
            last.next = cur2;
        }

        return result;
 }
 //迭代
 /**
 * Definition for singly-linked list.
 * public class ListNode 
 {
 *     int val;
 *     ListNode next;
 *     ListNode(int x) { val = x; }
 * }
 */
class Solution 
{
    public ListNode mergeTwoLists(ListNode l1, ListNode l2) 
    {
        if(l1==null)
        {
            return l2;
        }
        if(l2==null)
        {
            return l1;
        }
        ListNode result=null;
        ListNode last=null;

        ListNode cur1=l1;
        ListNode cur2=l2;
        while(cur1!=null&&cur2!=null)
        {
            if(cur1.val<=cur2.val)
            {
                if (result == null) 
                {
                    result = cur1;
                } 
                else 
                {
                    last.next = cur1;
                }
                last = cur1;
                cur1 = cur1.next;
            }
            else
            {
                if (result == null) 
                {
                    result = cur2;
                } 
                else 
                {
                    last.next = cur2;
                }
                last = cur2;
                cur2 = cur2.next;
            }
        }
        if (cur1 != null) 
        {
            last.next = cur1;
        } else 
        {
            last.next = cur2;
        }

        return result;
    }
}
//递归 
class Solution 
{
    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;
        }
    }
}

7. 链表的中间结点

给定一个带有头结点 head 的非空单链表,返回链表的中间结点。如果有两个中间结点,则返回第二个中间结点。
/**
 * Definition for singly-linked list.
 * public class ListNode {
 *     int val;
 *     ListNode next;
 *     ListNode(int x) { val = x; }
 * }
 */
class Solution 
{
    private int getLength(ListNode head) 
    {
        int len = 0;
        for (ListNode cur = head; cur != null; cur = cur.next) 
        {
            len++;
        }
        
        return len;
    }
    public ListNode middleNode(ListNode head) 
    {
        int len = getLength(head);
        int midLen = len / 2;
        ListNode node = head;
        for (int i = 0; i < midLen; i++) 
        {
            node = node.next;
        }
        
        return node;
    }
}
//快慢指针
//思路:快指针q每次走2步,慢指针p每次走1步,当q走到末尾时p正好走到中间
class Solution
{
    public ListNode middleNode(ListNode head)
    {
        ListNode q = head, p = head;
        while(q!= null && q.next != null)
        {
            p = p.next;
            q = q.next.next;
        }
        return p;
    }
}

8. 链表中倒数第k个结点

//快慢指针:两个指针的位置相差k-1个距离,当快指针走到最后一个节点的时候,
//慢指针指向的位置就是我们要的倒数第k个节点
/*
public class ListNode 
{
    int val;
    ListNode next = null;

    ListNode(int val) 
    {
        this.val = val;
    }
}*/
public class Solution 
{
    public ListNode FindKthToTail(ListNode head,int k) 
    {
        ListNode front = head;
        ListNode back = head;
        for (int i = 0; i < k; i++) 
        {
            if (front == null) 
            {
                return null;
            }
            front = front.next;
        }
        
        while (front != null) 
        {
            back = back.next;
            front = front.next;
        }
        return back;
    }
}
//方法二:倒数第K个结点等价于正向的链表长度len-k的结点
/*
public class ListNode 
{
    int val;
    ListNode next = null;

    ListNode(int val) 
    {
        this.val = val;
    }
}*/
public class Solution 
{
    public ListNode FindKthToTail(ListNode head,int k) 
    {
        int len=0;
        for(ListNode cur=head;cur!=null;cur=cur.next)
        {
            len++;
        }
        if(len<k)
        {
            return null;
        }
        int step=len-k;
        ListNode r=head;
        for(int i=0;i<step;i++)
        {
            r=r.next;
        }
        return r;
    }
}

9. 链表分割
以给定值x为基准将链表分割成两部分,所有小于x的结点排在大于或等于x的结点之前。给定一个链表的头指针 ListNode* pHead,请返回重新排列后的链表的头指针。注意:分割以后保持原来的数据顺序不变。

import java.util.*;

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

    ListNode(int val) 
    {
        this.val = val;
    }
}*/
public class Partition 
{
    public ListNode partition(ListNode pHead, int x) 
    {
        // < x
        ListNode less = null;
        ListNode lessLast = null;
        
        // >= x
        ListNode great = null;
        ListNode greatLast = null;
        
        ListNode cur = pHead;
        while (cur != null) 
        {
            if (cur.val < x) 
            {
                if (less == null) 
                {
                    less = cur;
                } 
                else 
                {
                    lessLast.next = cur;
                }
                lessLast = cur;
            } else 
            {
                if (great == null) 
                {
                    great = cur;
                } 
                else 
                {
                    greatLast.next = cur;
                }
                greatLast = cur;
            }   
            cur = cur.next;
        }
        
        if (less == null) 
        {
            return great;
        } 
        else 
        {
            lessLast.next = great;
            if (greatLast != null) 
            {
                greatLast.next = null;
            }
            return less;
        } 
    }
}

10. 链表的回文结构
题目描述
对于一个链表,请设计一个时间复杂度为O(n),额外空间复杂度为O(1)的算法,判断其是否为回文结构。
给定一个链表的头指针A,请返回一个bool值,代表其是否为回文结构。保证链表长度小于等于900。
测试样例:
1->2->2->1
返回:true

//思路:利用快慢指针法找到链表的中间结点,对中间结点后的链表进行反转,从头遍历对比元素值是否相等
import java.util.*;

/*
public class ListNode 
{
    int val;
    ListNode next = null;
    ListNode(int val) 
    {
        this.val = val;
    }
}*/
public class PalindromeList 
{
    public ListNode getMid(ListNode head) 
	{
        ListNode fast = head;
        ListNode slow = head;
        
        while (fast != null&&fast.next!=null) 
        {
            fast = fast.next.next;
            slow = slow.next;
        }
        return slow;
    }
    
    public ListNode reverse(ListNode head) 
	{
        ListNode result = null;
        ListNode cur = head;
        while (cur != null) 
        {
            ListNode next = cur.next;
            cur.next = result;
            result = cur;
            cur = next;
        }
        return result;
    }
    public boolean chkPalindrome(ListNode A) 
    {
        ListNode mid = getMid(A);
        ListNode h2 = reverse(mid);
        ListNode n1 = A;
        ListNode n2 = h2;
        while (n1 != null && n2 != null) 
        {
            if (n1.val != n2.val) 
            {
                return false;
            }
            n1 = n1.next;
            n2 = n2.next;
        }
        return true;
    }
}

11. 环形链表
给定一个链表,判断链表中是否有环

//快慢指针,快指针一次走两步,慢指针一次走一步,有环两者最终会相遇。
/**
 * 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) 
    {
        if(head==null||head.next==null)
        {
            return false;
        }
        ListNode fast=head;
        ListNode slow=head;
        while(fast!=null&&fast.next!=null)
        {
            fast=fast.next.next;
            slow=slow.next;
            if(fast==slow)
            {
                return true;
            }
        }
        return false;
    }
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值