• 链表类算法问题总结


    清明节做了leetcode上面所有的算法题目:封装了工具类,以后常用算法可以快速实现;

    代码:

    import java.util.*;
    
    /**
     * @Author liguo
     * @Description
     */
    
    public class wayListNode {
    
    
        //反转链表
        public ListNode reverse1(ListNode head) {
            if (head.next == null) return head;
            ListNode newHead = reverse1( head.next );
            head.next.next = head;
            head.next = null;
            return newHead;
        }
    
        //非递归实现链表的反转
        public ListNode reverse2(ListNode head) {
            if (head == null) return head;
            ListNode next, pre =null;
            while (head != null) {
                next = head.next;
                head.next = pre;
                pre = head;
                head = next;
            }
            return pre;
        }
    
        //输入两个链表,找出它们的第一个公共结点。
        //第一种方法
        public ListNode FindFirstCommonNode0(ListNode pHead1, ListNode pHead2) {
            if (pHead1 == null || pHead2 == null) {
                return null;
            }
    //遍历找到长度
            int count1 = 0;
            ListNode p1 = pHead1;
            while (p1 != null) {
                p1 = p1.next;
                count1++;
            }
            int count2 = 0;
            ListNode p2 = pHead2;
            while (p2 != null) {
                p2 = p2.next;
                count2++;
            }
    //计算长度,让长的走长度差个单位
            int flag = count1 - count2;
            if (flag > 0) {
                while (flag > 0) {
                    pHead1 = pHead1.next;
                    flag--;
                }
                while (pHead1 != pHead2) {
                    pHead1 = pHead1.next;
                    pHead2 = pHead2.next;
                }
                return pHead1;
            }
            if (flag <= 0) {
                while (flag < 0) {
                    pHead2 = pHead2.next;
                    flag++;
                }
                //移动到找相等
                while (pHead1 != pHead2) {
                    pHead2 = pHead2.next;
                    pHead1 = pHead1.next;
                }
                return pHead1;
            }
            return null;
        }
    
        //第二种解法.最简洁表达:
        public ListNode getIntersectionNode(ListNode headA, ListNode headB) {
            /**
             定义两个指针, 第一轮让两个到达末尾的节点指向另一个链表的头部, 最后如果相遇则为交点(在第一轮移动中恰好抹除了长度差)
             两个指针等于移动了相同的距离, 有交点就返回, 无交点就是各走了两条指针的长度
             **/
            if (headA == null || headB == null) return null;
            ListNode pA = headA, pB = headB;
            /**
             *在这里第一轮体现在pA和pB第一次到达尾部会移向另一链表的表头,
             而第二轮体现在如果pA或pB相交就返回交点, 不相交最后就是null==null
             */
            while (pA != pB) {
                pA = pA == null ? headB : pA.next;
                pB = pB == null ? headA : pB.next;
            }
            return pA;
        }
    
        //第三种,借助HashMap来实现,先把p1储存进hashmap,然后存储p2的时候, 看一下containsKey(),有就返回
        public ListNode FindFirstCommonNode(ListNode p1, ListNode p2) {
            HashMap <Integer, Integer> hashMap = new HashMap <>();
            while (p1 != null) {
                hashMap.put( p1.val, null );
                p1 = p1.next;
            }
            while (p2 != null) {
                if (hashMap.containsKey( p2.val )) return p2;
                p2 = p2.next;
            }
            return null;
        }
    
        //从尾到头打印链表
        //用栈
        public ArrayList <Integer> printListFromTailToHead0(ListNode listNode) {
            ArrayList arrayList = new ArrayList <Integer>();
            Stack stack = new Stack <Integer>();
            while (listNode.next != null) {
                stack.push( listNode.val );
                listNode = listNode.next;
            }
            if (!stack.isEmpty()) {
                arrayList.add( stack.pop() );
            }
            return arrayList;
        }
    
        //用vector往头部插入
        public Vector <Integer> printListFromTailToHead1(ListNode listNode) {
            Vector vector = new Vector <Integer>();
            while (listNode != null) {
                vector.insertElementAt( listNode.val, 0 );
                listNode = listNode.next;
            }
            return vector;
        }
    
    
        //输出该链表中倒数第k个结点
        //两次遍历, 第一次计算出总结点数, 并储存,再遍历输出
        public ListNode FindKthToTail(ListNode head, int k) {
            int num = 1;
            ListNode p1 = head;
            while (p1 != null) {
                num++;
                p1 = p1.next;
            }
            if (num <= k) return null;
    
            ListNode p2 = head;
            for (int i = 1; i < num - k; i++) {
                p2 = p2.next;
            }
    
            return p2;
        }
    
        //  环形链表
        //用set进行储存
        public boolean hasCycle(ListNode head) {
            Set <ListNode> set = new HashSet <>();
            boolean ans = false;
            while (head != null) {
                if (set.contains( head.val )) {
                    return true;
                } else {
                    set.add( head );
                    head = head.next;
                }
            }
            return false;
        }
    
        //快慢指针
        public boolean hasCycle1(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;
        }
    
        //环形链表返回入环的第一个值
        public ListNode detectCycle(ListNode head) {
            if (head == null) return null;
    // 步骤一:使用快慢指针判断链表是否有环
            ListNode p = head, p2 = head;
            boolean hasCycle = false;
            while (p2.next != null && p2.next.next != null) {
                p = p.next;
                p2 = p2.next.next;
                if (p == p2) {
                    hasCycle = true;
                    break;
                }
            }
            // 步骤二:若有环,找到入环开始的节点
            if (hasCycle) {
                ListNode q = head;
                while (p != q) {
                    p = p.next;
                    q = q.next;
                }
                return q;
            } else
                return null;
        }
    
        //删除链表中第k个值,
    
        /**
         * 一个指针先走n-1步,另一个指针从头开始向后走,当先走的那个走不下去的时候,
         * 另一个指针的位置就是待删除结点。 Java执行用时2ms
         *
         * @param head
         * @param n
         * @return
         */
        public static ListNode removeNthFromEnd(ListNode head, int n) {
            ListNode pioneer = head;
            for (int i = 0; i < n - 1; i++) {
                pioneer = pioneer.next;
            }
            //哨兵
            ListNode pre = new ListNode( -1 );
            ListNode start = pre;
            pre.next = head;
            while (pioneer.next != null) {
                pioneer = pioneer.next;
                pre = pre.next;
            }
            //执行删除操作
            pre.next = pre.next.next;
            return start.next;
        }
    
        //奇数偶数链表
        public ListNode oddEvenList(ListNode head) {
            if (head == null || head.next == null) return head;
            ListNode first = head;
            ListNode second = head.next;
            ListNode temp = second;
            while (second != null && second.next != null) {
                // 奇数放到奇数后面
                first.next = second.next;
                first = first.next;
                second.next = first.next;
                second = second.next;
            }
            // 把偶数的全部连接在后面
            first.next = temp;
            return head;
        }
    
        //回文链表
        public boolean isPalindrome(ListNode head) {
            //极端情况
            if (head == null || head.next == null) return true;
            //找中节点,反转链表,然后便利对比
    
            ListNode fast = head;
            ListNode slow = head;
            while (fast.next != null && fast.next.next != null) {
                fast = fast.next.next;
                slow = slow.next;
            }
            slow = reverse( slow.next );
    
    
            while (slow.next != null) {
                if (head.val != slow.val) return false;
                head = head.next;
                slow = slow.next;
            }
            return true;
        }
        private ListNode reverse(ListNode head) {
            if (head.next == null) return head;
            ListNode newHead = reverse( head.next );
            head.next.next = head;
            head.next = null;
            return newHead;
        }
        //合并两个有序链表
    
        public ListNode mergeTwoLists(ListNode l1, ListNode l2) {
            // 类似归并排序中的合并过程
            ListNode ans = new ListNode( 0 );
            ListNode cur = ans;
            while (l1 != null && l2 != null) {
                if (l1.val < l2.val) {
                    cur.next = l1;
                    cur = cur.next;
                    l1 = l1.next;
                } else {
                    cur.next = l2;
                    cur = cur.next;
                    l2 = l2.next;
                }
            }
            // 任一为空,直接连接另一条链表
            if (l1 == null) {
                cur.next = l2;
            } else {
                cur.next = l1;
            }
            return ans.next;
        }
        //两数 相加
            public ListNode addTwoNumbers(ListNode one,ListNode two){
                ListNode ans = new ListNode(0);
                ListNode p = one, q = two, curr = ans;
                int carry = 0;
                while (p != null || q != null) {
                    int x = (p != null) ? p.val : 0;
                    int y = (q != null) ? q.val : 0;
                    int sum = carry + x + y;
                    carry = sum / 10;
                    curr.next = new ListNode(sum % 10);
                    curr = curr.next;
                    if (p != null) p = p.next;
                    if (q != null) q = q.next;
                }
                if (carry > 0) {
                    curr.next = new ListNode(carry);
                }
                return ans.next;
            }
    
        //旋转链表
        public ListNode rotateRight(ListNode head, int k) {
    
            if (head == null || k==0) return head;
    
            // 获取长度,对k取模,并获得尾节点rear
            int length = 1;
            ListNode rear = null;
            for (rear=head; rear.next!=null; rear=rear.next) length++;
            k %= length;
    
            if (k==0) return head;
    
            // 遍历获得倒序第k+1个节点preSubEnd,倒序第k个节点postSubStart
            ListNode preSubEnd = null, postSubStart = head;
            while (k!=length)
            {
                preSubEnd = postSubStart;
                postSubStart = postSubStart.next;
                k++;
            }
    
            // preSubEnd为旋转后的尾节点,将原先的尾节点rear连接上原先的头节点head
            preSubEnd.next = null;
            rear.next = head;
    
            return postSubStart;
        }
    
    
    }
    View Code
  • 相关阅读:
    注册和登录与数据库内的链接
    数据访问
    马厩分配问题
    Codeforces Round #365 (Div. 2) D.Mishka and Interesting sum
    最优比例生成树模板
    01分数规划模板
    hiho一下第109周《Tower Defense Game》
    begin.BZOJ 1383: 三取方格数
    最小生成树
    Codeforces Round #364 (Div. 1)B. Connecting Universities
  • 原文地址:https://www.cnblogs.com/liguo-wang/p/10667779.html
Copyright © 2020-2023  润新知