zoukankan      html  css  js  c++  java
  • 算法-链表

    算法-链表

     

        云想衣裳花想容,春风拂槛露华浓。

    简介:算法-链表

    一、从尾到头打印链表

    1、题目描述

    输入一个链表的头节点,按链表从尾到头的顺序返回每个节点的值(用数组返回)。
    输入:
    {1,2,3}
    返回值:
    [3,2,1]

    2、解题思路

    使用递归

    要逆序打印链表 1->2->3(3,2,1),可以先逆序打印链表 2->3(3,2),最后再打印第一个节点 1。而链表 2->3 可以看成一个新的链表,要逆序打印该链表可以继续使用求解函数,也就是在求解函数中调用自己,这就是递归函数。

     1 import java.util.*;
     2 public class Solution {
     3     public ArrayList<Integer> printListFromTailToHead(ListNode listNode) {
     4         ArrayList<Integer> ret = new ArrayList<>();
     5         if (listNode != null) {
     6             // 递归
     7             ret.addAll(printListFromTailToHead(listNode.next));
     8             ret.add(listNode.val);
     9         }
    10         return ret;
    11     }
    12 }
    View Code

    二、删除链表中重复的节点

    1、题目描述

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

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

    2、解题思路

    借助辅助头结点,可避免单独讨论头结点的情况。设置两个结点 pre 和 cur,当 cur 和 cur.next 值相等,cur 一直向前走,直到不等退出循环,这时候 cur 指的值还是重复值,调整 cur 和 pre 的指针再次判断。

     1 /*
     2 删除链表中重复的结点
     3 */
     4 public class Solution {
     5     public ListNode deleteDuplication(ListNode pHead) {
     6         /*
     7         构建辅助头结点
     8         对于链表而言,不保存的意思也就是跳过这一结点next指向下一个结点
     9          */      
    10         ListNode head=new ListNode(-1);
    11         head.next=pHead;
    12         ListNode saveHead=head;//保存下来的结点
    13         ListNode currentNode=pHead;
    14         while(currentNode!=null){
    15             if(currentNode.next!=null && currentNode.val==currentNode.next.val) {//有重复了,跳过
    16                 while (currentNode.next != null && currentNode.val == currentNode.next.val) {
    17                     currentNode = currentNode.next;//跳过这些相同结点
    18                 }
    19                 currentNode=currentNode.next;//有重复,一个都不保存
    20                 saveHead.next=currentNode;//保存
    21             }
    22             else {
    23                 //这里是没重复的
    24                 saveHead=currentNode;
    25                 currentNode=currentNode.next;
    26             }
    27         }
    28         return head.next;
    29     }
    30 }
    View Code

    三、链表中倒数第K 个结点

    1、题目描述

    输入一个链表,输出一个链表,该输出链表包含原链表中从倒数第k 个结点至尾节点的全部节点。如果该链表长度小于k,请返回一个长度为 0 的链表。
    输入:
    {1,2,3,4,5},1 
    返回值:
    {5}

    2、解题思路

    在链表中:倒数的+顺数的长度等于链表总长度,所以可以设置两个指针,一个先走K 步,剩下的到链表的末尾要走的步数就是倒数第k个节点,需要从头开始走的步数。

     1 import java.util.*;
     2 
     3 /*
     4  链表中倒数最后k 个结点
     5  */
     6 public class Solution {
     7     public ListNode FindKthToTail (ListNode pHead, int k) {       
     8         ListNode first = pHead;
     9         for(int i = 0; i < k; i++){
    10             if(first == null){
    11                 return first;
    12             }
    13             first = first.next;
    14         }
    15         ListNode last = pHead;
    16         while(first != null){
    17             first = first.next;
    18             last = last.next;
    19         }
    20         return last;
    21     }
    22 }
    View Code

    四、链表中环的入口结点

    1、题目描述

    给一个链表,若其中包含环,请找出该链表的环的入口结点,否则,返回null。
    输入:
    {1,2},{3,4,5}
    返回值:
    3
    说明:
    返回环形链表入口节点,我们后台会打印该环形链表入口节点,即3 

    2、解题思路

    使用双指针,一个快指针 fast 每次移动两个节点,一个慢指针 slow 每次移动一个节点。因为存在环,所以两个指针必定相遇在环中的某个节点上。

    假设环入口节点为 y1,相遇所在节点为 z1。

    假设快指针 fast 在圈内绕了 N 圈,则总路径长度为 x+Ny+(N-1)z。z 为 (N-1) 倍是因为快慢指针最后已经在 z1 节点相遇了,后面就不需要再走了。

    而慢指针 slow 总路径长度为 x+y。

    因为快指针是慢指针的两倍,因此 x+Ny+(N-1)z = 2(x+y)。

    我们要找的是环入口节点 y1,也可以看成寻找长度 x 的值,因此我们先将上面的等值分解为和 x 有关:x=(N-2)y+(N-1)z。

    上面的等值没有很强的规律,但是我们可以发现 y+z 就是圆环的总长度,因此我们将上面的等式再分解:x=(N-2)(y+z)+z。这个等式左边是从起点x1 到环入口节点 y1 的长度,而右边是在圆环中走过 (N-2) 圈,再从相遇点 z1 再走过长度为 z 的长度。此时我们可以发现如果让两个指针同时从起点 x1 和相遇点 z1 开始,每次只走过一个距离,那么最后他们会在环入口节点相遇。

     1 /*
     2 链表中环的入口结点
     3 */
     4 public class Solution {
     5 
     6     public ListNode EntryNodeOfLoop(ListNode pHead) {
     7         if(pHead == null || pHead.next == null){
     8             return null;
     9         }
    10         ListNode slow = pHead;
    11         ListNode fast = pHead;
    12         do{
    13             fast = fast.next.next;
    14             slow = slow.next;
    15         }while(slow != fast);
    16         fast = pHead;
    17         while(slow != fast){
    18             slow = slow.next;
    19             fast = fast.next;
    20         }
    21         return slow;       
    22     }
    23 }
    View Code

    五、链表中环的入口结点

    1、题目描述

    输入一个链表,反转链表后,输出新链表的表头。
    输入:
    {1,2,3}
    返回值:
    {3,2,1}

    2、解题思路

    递归

     1 /*
     2 反转链表
     3 */
     4 public class Solution {
     5     public ListNode ReverseList(ListNode head) {
     6         if(head == null || head.next == null){
     7             return head;
     8         }
     9         ListNode next = head.next;      
    10         // 递归
    11         ListNode newHead = ReverseList(next);
    12         next.next = head;
    13         head.next = null;
    14         return newHead;
    15     }
    16 }
    View Code

     

     

     

    云想衣裳花想容

        春风拂槛露华浓

     

     

     

     

     

  • 相关阅读:
    ajax返回乱码的解决方案
    Javascript里使用Dom操作Xml
    ASP.NET 网站路径
    远程连接SQL Server
    缘 in English
    简单C#验证类
    js事件列表
    ArrayList用法
    下拉菜单遮挡层的解决方案
    正则表达式过滤HTML危险脚本
  • 原文地址:https://www.cnblogs.com/taojietaoge/p/15008200.html
Copyright © 2011-2022 走看看