zoukankan      html  css  js  c++  java
  • 链表(一)

    从尾到头打印链表

    翻转链表

    翻转链表II

    链表划分

    合并两个排序链表

    合并k个排序链表

    链表求和

    带环链表

    找出带环链表的环入口

     

     从尾到头打印链表

    输入一个链表,从尾到头打印链表每个节点的值。

    public class Solution {
        // 递归实现
        ArrayList<Integer> result = new ArrayList<>();
        public ArrayList<Integer> printListFromTailToHead(ListNode listNode){
            if(listNode != null){
                this.printListFromTailToHead(listNode.next);
                result.add(listNode.val);
            }
            return result;
        }
        
        // 借用stack
        public ArrayList<Integer> printListFromTailToHead3(ListNode listNode) {
            Stack<Integer> stack = new Stack<>();
            ArrayList<Integer> list = new ArrayList<>();
            while(listNode!=null){
                stack.push(listNode.val);
                listNode = listNode.next;
            }
            while(!stack.isEmpty()){
                list.add(stack.pop());
            }
            return list;
        }
    }

    翻转链表

    // 从头到尾遍历原链表,每遍历一个节点,将其摘下放在新链表的最前段, O(n)
    public ListNode reverse(ListNode head) {
        ListNode prev = null;
        ListNode cur = head;
        
        while (cur != null) {
            ListNode temp = cur; // 保存当前要处理的节点
            cur = cur.next;     // 跳到下一个节点
            temp.next = prev;
            prev = temp;
        }
        return prev;
    }
    
    // 递归
    public ListNode reverse2(ListNode head) {
        if (head == null || head.next == null) {
            return head;
        }
        
        ListNode reHead = reverse2(head.next);
        head.next.next = head;
        head.next = null;
        return reHead;
    }

     翻转链表II

    翻转链表中第m个节点到第n个节点的部分。(给出链表1->2->3->4->5->null, m = 2 和n = 4,返回1->4->3->2->5->null

    分析:对于m、n,确定要翻转2->3->4。先找到2的前一个节点,prev;按照普通翻转链表的做法,翻转n-m次;最后,node[m].next=node[n].next,prev.next=node[n]

    public ListNode reverseBetween(ListNode head, int m , int n) {
        if(head==null || head.next==null || m==n){
            return head;
        }
        
        ListNode pre;
        ListNode dummy = new ListNode(0);
        pre = dummy;
        dummy.next = head;
        
        for(int i=0; i<m-1; i++){
            pre = pre.next;
        }
        
        ListNode cur = pre.next, p = pre.next, node = null;
        for(int i=0; i<=n-m; i++){
            ListNode nxt = cur.next;
            cur.next =node;
            node=cur;
            cur = nxt;
        }
        
        p.next = cur;
        pre.next = node;
        return dummy.next;
    }

     链表划分

    给定一个单链表和数值x,划分链表使得所有小于x的节点排在大于等于x的节点之前。 保留两部分内链表节点原有的相对顺序。

    ( 链表 1->4->3->2->5->2->null,并且 x=3 返回 1->2->2->4->3->5->null )

    public ListNode partition(ListNode head, int x) {
        ListNode leftDummy = new ListNode(0);
        ListNode rightDummy = new ListNode(0);
        ListNode left = leftDummy, right = rightDummy;
        // 两个指针,left保存小于x的节点,right保存大于x的节点,最后left.next=rightDummy.next
        while (head != null) {
            if (head.val < x) {
                left.next = head;
                left = head;
            } else {
                right.next = head;
                right = head;
            }
            head = head.next;
        }
    
        right.next = null;
        left.next = rightDummy.next;
        return leftDummy.next;
    }

    合并两个排序链表

    将两个排序链表合并为一个新的排序链表

    (给出 1->3->8->11->15->null2->null, 返回 1->2->3->8->11->15->null。)

    public ListNode mergeTwoLists(ListNode l1, ListNode l2) {
        ListNode dummy = new ListNode(0);
        ListNode lastNode = dummy;
        
        while(l1!=null && l2!=null){
            if(l1.val<l2.val){
                lastNode.next = l1;
                l1 = l1.next;
            }else{
                lastNode.next = l2;
                l2 = l2.next;
            }
            
            lastNode = lastNode.next;
        }
        
        if(l1!=null){
            lastNode.next = l1;
        }else{
            lastNode.next = l2;
        }
        
        return dummy.next;
    }

     合并k个排序链表

    public ListNode mergeKLists(ListNode[] lists) {
        if(lists==null || lists.length==0)  return null;
        
        mergeKLists(lists, 0, lists.length-1);
        return lists[0];
    }
    
    public void mergeKLists(ListNode[] lists, int left, int right){
        if(left>=right)  return;
        
        int mid = left + (right+1-left)/2;
        mergeKLists(lists, left, mid-1);
        mergeKLists(lists, mid, right);
        
        ListNode dummy = new ListNode(0);
        merge2Lists(lists[left], lists[mid], dummy);
        lists[left] = dummy.next;
    }
    
    
    public void merge2Lists(ListNode l1, ListNode l2, ListNode dummy){
        if(l1==null && l2==null){
            return;
        }
        if(l1==null || (l2!=null && l2.val< l1.val)){
            dummy.next = l2;
            merge2Lists(l1, l2.next, dummy.next);
        }else if(l2==null || (l1!=null && l1.val<= l2.val)){
            dummy.next = l1;
            merge2Lists(l1.next, l2, dummy.next);
        }
    }

    链表求和

    两个用链表代表的整数,其中每个节点包含一个数字。数字存储按照在原来整数中相反的顺序,使得第一个数字位于链表的开头。写出一个函数将两个整数相加,用链表形式返回和。

    ( 给出两个链表(2 -> 4 -> 3) + (5 -> 6 -> 4),返回7 -> 0 -> 8 )

    public ListNode addLists(ListNode l1, ListNode l2) {
        if(l1 == null && l2 == null) {
            return null;
        }
            
        ListNode head = new ListNode(0);
        ListNode point = head;
        int carry = 0;    // 进位
        
        while(l1 != null && l2!=null){
            int sum = carry + l1.val + l2.val;
            point.next = new ListNode(sum % 10);    //本位上的数
            carry = sum / 10;    // 进位
            l1 = l1.next;
            l2 = l2.next;
            point = point.next;
        }
        
        while(l1 != null) {
            int sum =  carry + l1.val;
            point.next = new ListNode(sum % 10);
            carry = sum /10;
            l1 = l1.next;
            point = point.next;
        }
        
        while(l2 != null) {
            int sum =  carry + l2.val;
            point.next = new ListNode(sum % 10);
            carry = sum /10;
            l2 = l2.next;
            point = point.next;
        }
        
        if (carry != 0) {
            point.next = new ListNode(carry);
        }
        return head.next;
    }

    带环链表

    判断链表是否有环

    public boolean hasCycle(ListNode head) {
        if(head==null || head.next==null){
            return false;
        }
        
        ListNode slow = head;
        ListNode fast = head;
        while(fast!=null && fast.next!=null){
            slow = slow.next;
            fast = fast.next.next;
            if(slow == fast){
                return true;
            }
        }
        return false;
    }

    找出带环链表的环入口

    给定一个链表,如果链表中存在环,则返回到链表中环的起始节点的值,如果没有环,返回null。

    public ListNode detectCycle(ListNode head) {
        if(head==null || head.next==null || head.next.next==null)  
            return null;
            
        ListNode pointer1 = head.next;
        ListNode pointer2 = head.next.next;
        
        //Step 1
        while(pointer1!=pointer2){
            if(pointer2.next==null || pointer2.next.next==null)   
                return null;
            pointer1 = pointer1.next;
            pointer2 = pointer2.next.next;
        }
        pointer1 = head;
        
        //Step 2  p1从head开始,p2从交汇处开始,二者同时到达的位置就是环入口
        while(pointer1!=pointer2){
            pointer1 = pointer1.next;
            pointer2 = pointer2.next;
        }
        return pointer1;
    }
  • 相关阅读:
    历史书单
    《Tornado介绍》—— 读后总结
    基于TensorFlow的深度学习系列教程 2——常量Constant
    深度学习Tensorflow生产环境部署(下·模型部署篇)
    深度学习Tensorflow生产环境部署(上·环境准备篇)
    Crontab和sudo中无法使用TensorFlow ImportError libcublas.so.9.0
    基于TensorFlow的深度学习系列教程 1——Hello World!
    想要接触人工智能吗?先要学会如何阅读论文
    《数据挖掘与数据化运营实战 思路、方法、技巧与应用》—— 读书笔记
    《新参者》—— 读后总结
  • 原文地址:https://www.cnblogs.com/hesier/p/5587034.html
Copyright © 2011-2022 走看看