链表相关的算法-java实现

  1. 链表逆序-已知链表头节点head,将链表逆序
    /***
    * 链表逆序 已知链表头节点head,将链表逆序
    * @param head
    * @return
    */
   private static ListNode reverseList(ListNode head){
       ListNode new_head = null;
       while(head != null){
           ListNode next = head.next; //备份head.next
           head.next = new_head;  //更新head.next
           new_head = head;  //移动new_head
           head = next;  //遍历链表
       }
       return new_head;
   }
  1. 链表逆序,已知链表头节点,将链表从位置m到n逆序
    /***
    * 链表逆序,已知链表头节点,将链表从位置m到n逆序
    * @param head
    * @param m
    * @param n
    * @return
    */
   private static ListNode reverseBetween(ListNode head, int m, int n){
       int change_len = n - m + 1;//计算需要逆置的节点个数
       ListNode pre_head = null;  //初始化开始逆置的节点的前驱
       ListNode result = head;  //最终转换后的链表头节点,非特殊情况即为head
       while(head != null && --m > 0){ //将head向前移动m-1个位置
           pre_head = head;
           head = head.next;
       }

       ListNode modify_list_tail = head;  //将modify_list_tail指向当前head,即逆置后的链表尾
       ListNode new_head = null;
       while(head != null && change_len > 0){  //逆置change_len个节点
           ListNode next = head.next;
           head.next = new_head;
           new_head = head;
           head = next;
           change_len--;
       }

       modify_list_tail.next = head;  //连接逆置后的链表与逆置端的最后一个节点
       if(pre_head != null){   //如果pre_head不为空,说明不是从第一个节点开始逆置的 m > 1
           pre_head.next = new_head;  //将逆置链表开始的节点前驱与逆置后的节点链接
       }else{
           result = new_head;  //如果pre_head为空,说明m==1从第一个节点开始逆置,结果即为逆置后的链表
       }

       return result;
   }

  1. 求两个链表的交点
  /***
     * 求两个链表的交点
     * @param headA
     * @param headB
     * @return
     */
    private static ListNode getIntersectionNode(ListNode headA, ListNode headB){
        Set<ListNode> nodeSet = new HashSet<>();
        while(headA != null){
            nodeSet.add(headA);
            headA = headA.next;
        }
        while(headB != null){
            if(nodeSet.contains(headB)){
                return headB;
            }
            headB = headB.next;
        }

        return null;
    }
  1. 链表求环
  /***
    * 链表求环
    * @param head
    * @return
    */
   private static ListNode detectCycle(ListNode head){
       Set<ListNode> nodeSet = new HashSet<>();
       while(head != null){
           if(nodeSet.contains(head)){
               return head;
           }
           nodeSet.add(head);
           head = head.next;
       }

       return null;
   }

  1. 链表的划分
/***
     * 链表的划分,已知链表头指针heady与数值x, 将所有小于x的节点放在大于xde jiedian qian m
     * 并且保持这些节点的原来的相对位置。
     * @param head
     * @param x
     * @return
     */
    private static ListNode partition(ListNode head, int x){
        ListNode less_ptr = new ListNode();  //对应指针指向这两个头节点
        ListNode more_ptr = new ListNode();
        ListNode less_head = less_ptr;  //设置两个临时的头节点
        ListNode more_head = more_ptr;

        while(head != null){
            if(head.val < x){  //如果节点值小于x,则将该节点放入less_ptr之后
                less_ptr.next = head;
                less_ptr = head;  //链接完成后,less_ptr向后移动,指向head
            }else{    //否则将该节点放入more_ptr后
                more_ptr.next = head;
                more_ptr = head;
            }
            head = head.next;
        }

        less_ptr.next = more_head.next;   //将less链表尾与more链表头相连
        more_ptr.next = null;  //将链表尾部节点next置空

        return less_head.next;
    }
  1. 链表合并(2个链表)
    /***
    * 已知两个已排序链表头节点指针l1,l2,将这两个链表合并,合并后仍为有序的,返回合并后的头节点
    * @param l1
    * @param l2
    * @return
    */
   private static ListNode mergeTwoSortedList(ListNode l1, ListNode l2){
       ListNode pre = new ListNode();
       ListNode head = pre;
       head.next = pre;
       while(l1 != null && l2 != null){
           if(l1.val < l2.val){
               pre.next = l1;
               l1 = l1.next;     //移动l1
           }else{
               pre.next = l2;
               l2 = l2.next;    //移动l2
           }

           pre = pre.next;   //pre指向新连接的节点
       }

       if(l1 != null){   //l1有元素剩余
           pre.next = l1;
       }

       if(l2 != null){  //l2有元素剩余
           pre.next = l2;
       }

       return  head.next;
   }
  1. 链表合并(多个链表)
/***
    * 合并已排序的链表(多个)
    * @param listK
    * @return
    */
   private static ListNode mergeKList(List<ListNode> listK){
       if(listK == null || listK.size() == 0){
           return null;
       }

       if(listK.size() == 1){
           return listK.get(0);
       }

       if(listK.size() == 2){
           return mergeTwoSortedList(listK.get(0), listK.get(1));
       }

       int mid = listK.size() / 2;
       List<ListNode> sub1List = new ArrayList<>();
       List<ListNode> sub2List = new ArrayList<>();
       for(int i = 0; i < mid; i++){  //拆分listK为两个子lists
           sub1List.add(listK.get(i));
       }
       for(int i = mid; i < listK.size(); i++){
           sub2List.add(listK.get(i));
       }

       ListNode list1 = mergeKList(sub1List);
       ListNode list2 = mergeKList(sub2List);

       return mergeTwoSortedList(list1, list2);
   }
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值