算法练习LeetCode初级算法之链表

  • 删除链表中的节点

/**

* 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;

}

}

  • 删除链表的倒数第N个节点

  • 两次遍历算法

    class Solution {

    public ListNode removeNthFromEnd(ListNode head, int n) {

        ListNode dummy=new ListNode(0);

        dummy.next=head;

        int length=0;

        ListNode p=head;

        while (p!=null) {

                length++;

                p=p.next;

            }

        ListNode first=dummy;

        length-=n;

        while (length>0) {

                length--;

                first=first.next;

            }

        first.next=first.next.next;

        return dummy.next;

    }

    }

  • 一次遍历算法

    class Solution {

        public ListNode removeNthFromEnd(ListNode head, int n) {

         ListNode dummy = new ListNode(0);

         dummy.next = head;

         ListNode first = dummy;

         ListNode second = dummy;

         // Advances first pointer so that the gap between first and second is n nodes apart

         for (int i = 1; i <= n + 1; i++) {

         first = first.next;

         }

         // Move first to the end, maintaining the gap

         while (first != null) {

         first = first.next;

         second = second.next;

         }

         second.next = second.next.next;

         return dummy.next;

        }

    }

  • 反转链表

  • 我的解法:利用Linklist比较好理解,有点投机取巧,面试不一定可以得吧!!!哈哈哈,但是测试通过了

    class Solution {

    public ListNode reverseList(ListNode head) {

            LinkedList<Integer> list=new LinkedList<>();

            for(ListNode x=head;x!=null;x=x.next) {

                list.add(x.val);

            }

            for(ListNode x=head;x!=null;x=x.next) {

                x.val=list.removeLast();

            }

        return head;

    }

    }

  • 迭代法,一开始不好理解,仔细琢磨后还是很好理解的

    class Solution {

    public ListNode reverseList(ListNode head) {

            if (head==null||head.next==null) {

                return head;

            }

            ListNode newHead=null;

            while (head!=null) {

                ListNode temp=head.next;//先把后面的数据储存到temp

                head.next=newHead;//head添加到newHead

                newHead=head;//head添加到newHeadnewHead重新作为新的头指针

                head=temp;//让头指针指向下一个数据,已保存在temp

            }

        return newHead;

    }

    }

  • 递归法,仔细研究后还是可以理解的

    class Solution {

    public ListNode reverseList(ListNode head) {

        return newHead(head);

    }

    public ListNode newHead(ListNode head) {

            if (head==null||head.next==null) {

                return head;

            }

            ListNode newHead=newHead(head.next);

            head.next.next=head;//反转链表,把把下一个数连接到newHead

            head.next=null;//指向空,防止再次递归导致覆盖后面的内容。

        return newHead;

        }

    }

    以上两种方法,通过从网站学习理解,必须站在巨人的肩膀上,哈哈哈!

    注明学习网址:https://blog.csdn.net/fx677588/article/details/72357389,虽然不是转载,但有借鉴。

  • 合并两个有序链表

  • 我的解法:很好实现,思路简单,但耗时长一点

    class Solution {

    public ListNode mergeTwoLists(ListNode l1, ListNode l2) {

            LinkedList<Integer> list=new LinkedList<>();

            for(ListNode x=l1;x!=null;x=x.next)

            {

                list.add(x.val);

            }

            for(ListNode x=l2;x!=null;x=x.next) {

                list.add(x.val);

            }

            Collections.sort(list);

            ListNode head=null;

            for (int i = list.size()-1; i>=0; i--) {

                ListNode n=new ListNode(list.get(i));

                n.next=head;

                head=n;

            }

        return head;

    }

    }

  • 大神一解法,递归解法,代码简洁

    class Solution {

    public ListNode mergeTwoLists(ListNode l1, ListNode l2) {

    ListNode rspHead=new ListNode(0);

    ListNode rsp=rspHead;

    while(l1!=null && l2!=null){

    if(l1.val<l2.val){

    rspHead.next=l1;

    rspHead=rspHead.next;

    l1=l1.next;

    }else{

    rspHead.next=l2;

    rspHead=rspHead.next;

    l2=l2.next;

    }

    }

    if(l1==null){

    rspHead.next=l2;

    }else{

    rspHead.next=l1;

    }

    return rsp.next;

    }

    }

  • 大神二解法,利用双指针,现将带头链表头指针用rsp保存,最后返回rsp.next

    class Solution {

    public ListNode mergeTwoLists(ListNode l1, ListNode l2) {

    ListNode rspHead=new ListNode(0);

    ListNode rsp=rspHead;

    while(l1!=null && l2!=null){

    if(l1.val<l2.val){

    rspHead.next=l1;

    rspHead=rspHead.next;

    l1=l1.next;

    }else{

    rspHead.next=l2;

    rspHead=rspHead.next;

    l2=l2.next;

    }

    }

    if(l1==null){

    rspHead.next=l2;

    }else{

    rspHead.next=l1;

    }

    return rsp.next;

    }

    }

  • 回文链表

  • 我的解法:感觉已经脱离了链表,不行,不好,时间太长!

    class Solution {

    public boolean isPalindrome(ListNode head) {

            if (head==null||head.next==null) {

                return true;

            }

            LinkedList<Integer> list=new LinkedList<>();

            for(ListNode x=head;x!=null;x=x.next) {

                list.add(x.val);

            }

            for (int i = 0; i < list.size()/2; i++) {

                if (list.get(i).compareTo(list.get(list.size()-i-1))!=0){

                    return false;

                }

            }

        return true;

    }

    }

  • 大神解法:挺好!先找链表中点,然后再反转后半部分,最后再分别遍历比较,直到后半部分遍历完!

    class Solution {

        ListNode node1=new ListNode(0);

        ListNode node2=new ListNode(0);

    public boolean isPalindrome(ListNode head) {

            if (head==null||head.next==null) {

                return true;

            }

            ListNode slow=head;

            ListNode fast=head;

            while (fast.next!=null&&fast.next.next!=null) {

                fast=fast.next.next;

                slow=slow.next;

            }

            slow=reverse(slow.next);//此处如果是show的话,将从中点的前一个匹配,比较难理解,后面附图说明

            while (slow!=null) {

                if (head.val!=slow.val) {//到这里,head短的话会成为空指针而报错!!!

                    return false;

                }

                head=head.next;

                slow=slow.next;

            }

        return true;

    }

    private ListNode reverse(ListNode head) {

            if (head==null||head.next==null) {

                return head;

            }

            ListNode newHead=reverse(head.next);

            head.next.next=head;

            head.next=null;

        return newHead;

        }

    }

说明:如果测试样例输入0,0的话,黄色标记为什么会报错!

  • 环形链表

  • 我的解法:利用hashset

    class Solution {

    public boolean hasCycle(ListNode head) {

        if (head==null||head.next==null) {

                return false;

            }

            Set<ListNode> set=new HashSet<>();

            int n=0;

            ListNode x=head;

        while (set.size()>=n) {

            set.add(x);

            x=x.next;

            n++;

            if (x==null) {

                    return false;

                }

            }

        return true;

    }

    }

  • 大神解法:

    class Solution {

    public boolean hasCycle(ListNode head) {

        if (head==null) {

                return false;

            }

        ListNode l1=head,l2=head.next;

        while (l1!=null&&l2!=null&&l2.next!=null) {

                l1=l1.next;

                l2=l2.next.next;

                if (l1==l2) {

                    return true;

                }

            }

        return false;

    }

    }

  • 递归解法,更为简洁

    class Solution {

    public boolean hasCycle(ListNode head) {

    if(head==null||head.next==null)return false;

    if(head.next==head)return true;

    ListNode l=head.next;

    head.next=head;

    boolean isCycle=hasCycle(l);

    return isCycle;

    }

    }

原文地址:https://www.cnblogs.com/GavinYGM/p/10333776.html