• 牛客题目——链表中倒数最后k个结点、两个链表的第一个公共结点、二叉搜索树的最近公共祖先



    题目1——链表中倒数最后k个结点

    输入一个长度为n的链表,设链表中的元素的值为ai,返回该链表中倒数第k个结点。
    如果该链表长度小于k,请返回一个长度为0的链表。
    要求:空间复杂度O(n),时间复杂度O(n)

    示例
    输入:{1,2,3,4,5}, 2
    输出:{4,5}
    输入:{2}, 8
    输出:{}

    解题思路

    使用快慢指针,快指针先移动k步,慢指针再从头移动,这时候两个指针同时移动,当快指针到链表的末尾的时候,返回第二个指针即可。

    利用栈,首先将原链表的结点全部压入到栈当中,然后再把栈中最上面的k个结点出栈,出栈的结点重新串成一个新的链表。

    代码实现

    import java.util.*;
    /*
     * public class ListNode {
     *   int val;
     *   ListNode next = null;
     *   public ListNode(int val) {
     *     this.val = val;
     *   }
     * }
     */
    public class Solution {
        public ListNode FindKthToTail (ListNode pHead, int k) {
            ListNode dummy = pHead;
            ListNode prek = new ListNode(0);
            prek = pHead;
            for(int i=0;i<k;i++){
                if(prek != null)
                    prek  = prek.next;
                else return null;
            }
            while(prek != null){
                dummy = dummy.next;
                prek = prek.next;
            }
            return dummy;  
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    import java.util.*;
    
    /*
     * public class ListNode {
     *   int val;
     *   ListNode next = null;
     *   public ListNode(int val) {
     *     this.val = val;
     *   }
     * }
     */
    public class Solution {
        public ListNode FindKthToTail (ListNode pHead, int k) {
            ListNode res = new ListNode(0);
            Stack<ListNode> st = new Stack<ListNode>();
            while(pHead != null){
                st.push(pHead);
                pHead = pHead.next;
            }
            for(int i=0;i<k;i++){
                if(st.isEmpty())
                    return null;
                ListNode tmp = st.pop();
                if(res.next == null){
                    res.next = tmp;
                }else{
                    tmp.next = res.next;
                    res.next = tmp;
                }
            }
            return res.next;
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33

    题目2——两个链表的第一个公共结点

    输入两个无环的单向链表,找出它们的第一个公共结点,如果没有公共结点则返回空。
    要求:空间复杂度O(1),时间复杂度O(n)

    在这里插入图片描述

    解题思路

    利用双指针,若两个链表存在公共结点,则两个指针以同样的速度走完同样的长度(链表1+链表2),一定会相遇;而没有公共结点的时候,两个指针都会走到终点,此时都为空。

    或者是利用集合,将第一个链表中的所有结点存放到集合中,然后遍历第二个链表,判断其是否存在集合中,如果存在,则返回这个结点,否则遍历后没有找到,则说明没有相交,返回null即可。

    代码实现

    import java.util.*;
    /*
    public class ListNode {
        int val;
        ListNode next = null;
    
        ListNode(int val) {
            this.val = val;
        }
    }*/
    public class Solution {
        public ListNode FindFirstCommonNode(ListNode pHead1, ListNode pHead2) {
            if(pHead1 == null || pHead2 == null)
                return null;
            ListNode p1 = pHead1;
            ListNode p2 = pHead2;
            while(p1 != p2){
                p1 = (p1 == null)?pHead2:p1.next;
                p2 = (p2 == null)?pHead1:p2.next;
            }
            return p1;
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    import java.util.*;
    /*
    public class ListNode {
        int val;
        ListNode next = null;
    
        ListNode(int val) {
            this.val = val;
        }
    }*/
    public class Solution {
        public ListNode FindFirstCommonNode(ListNode pHead1, ListNode pHead2) {
            if(pHead1 == null || pHead2 == null)
                return null;
            ListNode p1 = pHead1;
            ListNode p2 = pHead2;
            Set<ListNode> set = new HashSet<ListNode>();
            while(p1 != null){
                set.add(p1);
                p1 = p1.next;
            }
            while(p2 != null){
                if(!set.contains(p2)){
                    p2 = p2.next;
                }else
                    return p2;
            }
            return null;
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30

    题目3——二叉搜索树的最近公共祖先

    给定一个二叉搜索树,找到该树种两个指定结点的最近公共祖先。
    最近公共祖先定义:对于有根树T的两个结点p、q,最近公共祖先LCA(T,p,q)表示一个结点x,满足x是p和q的祖先且x的深度尽可能大。在这里,一个结点也可以是它自己的祖先。

    示例
    输入:{7,1,12,0,4,11,14,#,#,3,5},1,12
    输入:7
    在这里插入图片描述

    解题思路

    首先检查空结点,空树没有公共祖先;
    比较两个结点的值,若都小于根结点,则p,q结点都在该结点的左侧,公共祖先在左子树中,递归进入左子树;
    若都大于根结点,则公共祖先都在右子树中,递归进入右子树;
    否则,返回最近公共祖先即为根结点。

    找到两个结点的路径,然后将路径中的结点存放到数组当中,比较两个数组,最后一个相等的元素就是最近的公共祖先。
    寻找路径时,根据二叉搜索树的性质,当前结点的值比目标大,则进入左子树,否则进入右子树。

    代码实现

    import java.util.*;
    /*
     * public class TreeNode {
     *   int val = 0;
     *   TreeNode left = null;
     *   TreeNode right = null;
     *   public TreeNode(int val) {
     *     this.val = val;
     *   }
     * }
     */
    public class Solution {
        public int lowestCommonAncestor (TreeNode root, int p, int q) {
            if(root == null)
                return -1;
            if(p<root.val && q<root.val)
                return lowestCommonAncestor(root.left,p,q);
            if(p>root.val && q>root.val)
                return lowestCommonAncestor(root.right,p,q);
            return root.val;
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    import java.util.*;
    /*
     * public class TreeNode {
     *   int val = 0;
     *   TreeNode left = null;
     *   TreeNode right = null;
     *   public TreeNode(int val) {
     *     this.val = val;
     *   }
     * }
     */
    public class Solution {
        public ArrayList<Integer> getPath(TreeNode root,int target){
            ArrayList<Integer> path = new ArrayList<Integer>();
            while(root.val != target){
                path.add(root.val);
                if(target<root.val)
                    root = root.left;
                else
                    root = root.right;
            }
            path.add(root.val);
            return path;
        }
        public int lowestCommonAncestor (TreeNode root, int p, int q) {
            ArrayList<Integer> path_p = getPath(root,p);
            ArrayList<Integer> path_q = getPath(root,q);
            int res = 0;
            for(int i=0;i<Math.min(path_p.size(),path_q.size());i++){
                int x = path_p.get(i);
                int y = path_q.get(i);
                if(x == y)
                    res = path_p.get(i);
                else
                    break;
            }
            return res;
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
  • 相关阅读:
    物联网测试数据构造实践
    【力扣】42. 接雨水
    LangChain与WebSocket:实时通信的新纪元
    在网络中加入新的模块时,有办法不影响原来的网络层次名字吗
    【工作总结】努力工作为什么感觉没用
    【图像处理】【应用程序设计】加载,编辑和保存图像数据、图像分割、色度键控研究(Matlab代码实现)
    LeetCode-653. Two Sum IV - Input is a BST [C++][Java]
    智能合约检测:新一代区块链技术的安全守护
    Mysql索引(究极无敌细节版)
    4.12每日一题(通过全微分判断多元函数最大最小值)
  • 原文地址:https://blog.csdn.net/zhangzhang_one/article/details/125551885