• 算法练习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;

      }

      }

  • 相关阅读:
    Linux常见问题解决
    使用npm国内镜像
    常用CSS备忘
    如何把JavaScript数组中指定的一个元素移动到第一位
    教你如何将word中的表格完美粘贴到ppt中
    测试开发之路--一个小小工程师的回首
    一篇文章读完50篇摄影教程(托马斯的2016总结)
    李开复推荐的30本创业/管理/互联网必须看的电子书
    摩拜单车深度产品体验报告
    Word2016(2013)怎么从任意页插入起始页码
  • 原文地址:https://www.cnblogs.com/GavinYGM/p/10333776.html
Copyright © 2020-2023  润新知