首页 > 其他分享 >Google模拟面试【面试】

Google模拟面试【面试】

时间:2024-01-02 13:37:08浏览次数:37  
标签:Node Google int 面试 right static root 模拟 left


Google模拟面试【面试】

2023-12-25 16:00:42

Google代码面试

Prompt #1

给一个二叉树,定义深度为结点到根;所要遍历的边的数量。
示例二叉树中8的深度为3,1的深度为0。
编写函数返回这个二叉树的所有结点的深度和。
示例二叉树答案是16

1
        /  \
      2      3
     / \    / \
    4   5  6   7
   / \
  8   9
public class Main {
    static class Node{
        int val;
        Node left;
        Node right;

        public Node(int v){
            val=v;
        }

    }



    public static void main(String[] args) {
        Node a=new Node(1);
        Node b=new Node(2);
        Node c=new Node(3);
        Node d=new Node(4);
        Node e=new Node(5);
        Node f=new Node(6);
        Node g=new Node(7);
        Node h=new Node(8);
        Node i=new Node(9);
        a.left=b;
        a.right=c;
        b.left=d;
        b.right=e;
        c.left=f;
        c.right=g;
        d.left=h;
        d.right=i;

        int res1=solve1(a);
        System.out.println(res1);//16


    }

    public static int solve1(Node root){
        sum=0;
        sumDepths(root,0);
        return  sum;
    }



    static int sum;


    public static void sumDepths(Node root,int depth){
        sum+=depth;
        if(root.left!=null){
            sumDepths(root.left,depth+1);
        }
        if(root.right!=null){
            sumDepths(root.right,depth+1);
        }
    }



}

Prompt #2

返回每一个结点的子树深度的和,求和

示例二叉树答案是26

树型dp
对于结点x,有两个孩子,y,z
x子树结点个数=1+y的子树结点个数+z的子树结点个数
x子树深度和=(y的子树结点个数+y的子树深度和)+(z的子树结点个数+z的子树深度和)
因为对于孩子y的每个结点来说,其对于y的双亲x的深度都是加了x->y的一条边。
特殊:叶子结点(1,0)

过程分析
8,9,5,6,7:(1,0)
4,3:(3,2)
2:(5,6)
1:(9,16)

2+2+6+16=26

public static int solve2(Node root) {
        ans=0;
        dfs(root);
        return ans;
    }

    static class Info{
        int numNodes;
        int sumDepths;

        public Info(int a,int b){
            numNodes=a;
            sumDepths=b;
        }
    }

    static int ans;

    static Info dfs(Node root){
        Info pInfo=new Info(1,0);
        if(root.left!=null){
            Info cInfo=dfs(root.left);
            pInfo.sumDepths+=cInfo.sumDepths+cInfo.numNodes;
            pInfo.numNodes+=cInfo.numNodes;
        }
        if(root.right!=null){
            Info cInfo=dfs(root.right);
            pInfo.sumDepths+=cInfo.sumDepths+cInfo.numNodes;
            pInfo.numNodes+=cInfo.numNodes;
        }
        ans+= pInfo.sumDepths;
        return  pInfo;

    }

Prompt #3

求出所有节点到目标结点的深度和
比如到4的深度和是18

1
        /  \
      2      3
     / \    / \
    4   5  6   7
   / \
  8   9

分析可以得出
到一个目标结点的深度和=
到根结点的目标和-子树中的结点数量+其他结点数量(子树之外的结点数)
其他结点数量=总结点数量-子树结点数量

dfs1把每个子树及其对应的结点数存入到map中
运行结果

<Node1,9>,<Node2,5>,<Node3,3>,<Node4,3>
<Node5,1>,<Node6,1>,<Node7,1>,<Node8,1>,<Node9,1>,
n=root.numNodes=9
sumDists=root.sumDepth=16

模拟运行,忽略其他结点
dfs2(1,16,4)
左分支:newDists=16-5+(9-5)=15
dfs2(2,15,4)
右分支:newDists=15-3+(9-3)=18
dfs(4,18,4)
ans=18
会继续遍历所有结点,但是答案只会保存一个

//视频中把每个子树的结点数信息放到结点中
    //我把其放到哈希表中
    static HashMap<Node,Integer> map;

    //总结点个数
    static int n;

    static int solve3(Node root,Node target){
        ans=0;
        map=new HashMap<>();
        sumDists(root,target);
        return ans;
    }


    //把每个子树的结点数放到对应结点和结点数的map中
    static Info dfs1(Node root){
        Info pInfo=new Info(1,0);
        if(root.left!=null){
            Info cInfo=dfs1(root.left);
            pInfo.sumDepths+=cInfo.sumDepths+cInfo.numNodes;
            pInfo.numNodes+=cInfo.numNodes;
        }
        if(root.right!=null){
            Info cInfo=dfs1(root.right);
            pInfo.sumDepths+=cInfo.sumDepths+cInfo.numNodes;
            pInfo.numNodes+=cInfo.numNodes;
        }
        //和dfs的区别只有此处
        map.put(root, pInfo.numNodes);
        return  pInfo;

    }

    static void dfs2(Node u,int sumDists,Node target){
        if(u==target){
            ans=sumDists;
        }
        if(u.left!=null){
            int newSumDists=sumDists-map.get(u.left)+(n-map.get(u.left));
            dfs2(u.left,newSumDists,target);
        }
        if(u.right!=null){
            int newSumDists=sumDists-map.get(u.right)+(n-map.get(u.right));
            dfs2(u.right,newSumDists,target);
        }
    }

    static int sumDists(Node root,Node target){
        Info info=dfs1(root);
        n=info.numNodes;
        dfs2(root,info.sumDepths,target);
        return ans;
    }

补充 #3用图来解决

到4的深度和为18

1
        /  \
      2      3
     / \    / \
    4   5  6   7
   / \
  8   9
2,8,9到4的深度都是1
1,5到4的深度都是2
3到4的深度是3
6,7到4的深度都是4
1*3+2*2+3+2*4=18

一个bfs

//用图的方法解决
    //设置访问数组
    static HashMap<Node,Boolean> visited;

    static int solve(Node root,Node target){
        ans=0;
        visited=new HashMap<>();
        
        //图,hashmap可以更快找到,而没有采取下标对应结点
        HashMap<Node,ArrayList<Node>> graph=new HashMap<>();
        //树转为双向图,并且设置访问数组
        toGraph(root,graph);
        //广度优先遍历
        bfs(graph,target);
        return ans;
    }

    //深度优先转为双向图
    static void toGraph(Node root,HashMap<Node,ArrayList<Node>> graph){
        if(!graph.containsKey(root)){
            graph.put(root,new ArrayList<>());
        }
        if(root.left!=null){
            graph.get(root).add(root.left);
            toGraph(root.left,graph);
            graph.get(root.left).add(root);
        }
        if(root.right!=null){
            graph.get(root).add(root.right);
            toGraph(root.right,graph);
            graph.get(root.right).add(root);
        }
        visited.put(root,false);
    }

    static void bfs(HashMap<Node,ArrayList<Node>> graph,Node target){
        visited.put(target,true);
        Queue<Node> queue=new ArrayDeque<>();
        
        //加入第一层
        for (Node v:graph.get(target)){
            queue.offer(v);
        }

        //第一层深度为1
        int height=1;
        while (!queue.isEmpty()){
            int size=queue.size();
            
            //每次遍历一层
            for (int i = 0; i < size; i++) {
                Node v=queue.poll();
                if (!visited.get(v)){
                    //设置访问数组
                    visited.put(v,true);
                    //记录答案
                    ans+=height;

                    //下一层添加
                    for (Node next:graph.get(v)) {
                        queue.offer(next);
                    }
                }
            }
            //下一次深度+1
            height++;
        }
    }

所有代码

import java.util.ArrayDeque;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.Queue;

public class Main {
    static class Node{
        int val;
        Node left;
        Node right;

        public Node(int v){
            val=v;
        }

    }



    public static void main(String[] args) {
        Node a=new Node(1);
        Node b=new Node(2);
        Node c=new Node(3);
        Node d=new Node(4);
        Node e=new Node(5);
        Node f=new Node(6);
        Node g=new Node(7);
        Node h=new Node(8);
        Node i=new Node(9);
        a.left=b;
        a.right=c;
        b.left=d;
        b.right=e;
        c.left=f;
        c.right=g;
        d.left=h;
        d.right=i;

        int res1=solve1(a);
        System.out.println(res1);//16

        int res2=solve2(a);
        System.out.println(res2);//26

        int res3=solve3(a,d);
        System.out.println(res3);//18

        //使用图来解决#3
        int res=solve(a,d);
        System.out.println(res);//18

    }

    //--------------------------------------------------------------------

    public static int solve1(Node root){
        sum=0;
        sumDepths(root,0);
        return  sum;
    }



    static int sum;


    public static void sumDepths(Node root,int depth){
        sum+=depth;
        if(root.left!=null){
            sumDepths(root.left,depth+1);
        }
        if(root.right!=null){
            sumDepths(root.right,depth+1);
        }
    }

    //--------------------------------------------------------------------

    public static int solve2(Node root) {
        ans=0;
        dfs(root);
        return ans;
    }

    static class Info{
        int numNodes;
        int sumDepths;

        public Info(int a,int b){
            numNodes=a;
            sumDepths=b;
        }
    }

    static int ans;

    static Info dfs(Node root){
        Info pInfo=new Info(1,0);
        if(root.left!=null){
            Info cInfo=dfs(root.left);
            pInfo.sumDepths+=cInfo.sumDepths+cInfo.numNodes;
            pInfo.numNodes+=cInfo.numNodes;
        }
        if(root.right!=null){
            Info cInfo=dfs(root.right);
            pInfo.sumDepths+=cInfo.sumDepths+cInfo.numNodes;
            pInfo.numNodes+=cInfo.numNodes;
        }
        ans+= pInfo.sumDepths;
        return  pInfo;

    }

    //--------------------------------------------------------------------

    //视频中把每个子树的结点数信息放到结点中
    //我把其放到哈希表中
    static HashMap<Node,Integer> map;

    //总结点个数
    static int n;

    static int solve3(Node root,Node target){
        ans=0;
        map=new HashMap<>();
        sumDists(root,target);
        return ans;
    }


    //把每个子树的结点数放到对应结点和结点数的map中
    static Info dfs1(Node root){
        Info pInfo=new Info(1,0);
        if(root.left!=null){
            Info cInfo=dfs1(root.left);
            pInfo.sumDepths+=cInfo.sumDepths+cInfo.numNodes;
            pInfo.numNodes+=cInfo.numNodes;
        }
        if(root.right!=null){
            Info cInfo=dfs1(root.right);
            pInfo.sumDepths+=cInfo.sumDepths+cInfo.numNodes;
            pInfo.numNodes+=cInfo.numNodes;
        }
        //和dfs的区别只有此处
        map.put(root, pInfo.numNodes);
        return  pInfo;

    }

    static void dfs2(Node u,int sumDists,Node target){
        if(u==target){
            ans=sumDists;
        }
        if(u.left!=null){
            int newSumDists=sumDists-map.get(u.left)+(n-map.get(u.left));
            dfs2(u.left,newSumDists,target);
        }
        if(u.right!=null){
            int newSumDists=sumDists-map.get(u.right)+(n-map.get(u.right));
            dfs2(u.right,newSumDists,target);
        }
    }

    static int sumDists(Node root,Node target){
        Info info=dfs1(root);
        n=info.numNodes;
        dfs2(root,info.sumDepths,target);
        return ans;
    }

    //--------------------------------------------------------------------


    //用图的方法解决
    //设置访问数组
    static HashMap<Node,Boolean> visited;

    static int solve(Node root,Node target){
        ans=0;
        visited=new HashMap<>();

        //图,hashmap可以更快找到,而没有采取下标对应结点
        HashMap<Node,ArrayList<Node>> graph=new HashMap<>();
        //树转为双向图,并且设置访问数组
        toGraph(root,graph);
        //广度优先遍历
        bfs(graph,target);
        return ans;
    }

    //深度优先转为双向图
    static void toGraph(Node root,HashMap<Node,ArrayList<Node>> graph){
        if(!graph.containsKey(root)){
            graph.put(root,new ArrayList<>());
        }
        if(root.left!=null){
            graph.get(root).add(root.left);
            toGraph(root.left,graph);
            graph.get(root.left).add(root);
        }
        if(root.right!=null){
            graph.get(root).add(root.right);
            toGraph(root.right,graph);
            graph.get(root.right).add(root);
        }
        visited.put(root,false);
    }

    static void bfs(HashMap<Node,ArrayList<Node>> graph,Node target){
        visited.put(target,true);
        Queue<Node> queue=new ArrayDeque<>();

        //加入第一层
        for (Node v:graph.get(target)){
            queue.offer(v);
        }

        //第一层深度为1
        int height=1;
        while (!queue.isEmpty()){
            int size=queue.size();

            //每次遍历一层
            for (int i = 0; i < size; i++) {
                Node v=queue.poll();
                if (!visited.get(v)){
                    //设置访问数组
                    visited.put(v,true);
                    //记录答案
                    ans+=height;

                    //下一层添加
                    for (Node next:graph.get(v)) {
                        queue.offer(next);
                    }
                }
            }
            //下一次深度+1
            height++;
        }
    }


}

2023-12-25 19:10:43


标签:Node,Google,int,面试,right,static,root,模拟,left
From: https://blog.51cto.com/u_15719556/9068243

相关文章

  • #yyds干货盘点# LeetCode程序员面试金典:赎金信
    给你两个字符串:ransomNote 和 magazine ,判断 ransomNote 能不能由 magazine 里面的字符构成。如果可以,返回 true ;否则返回 false 。magazine 中的每个字符只能在 ransomNote 中使用一次。 示例1:输入:ransomNote="a",magazine="b"输出:false示例2:输入:ransomNot......
  • #yyds干货盘点# LeetCode程序员面试金典:按权重随机选择
    题目给你一个下标从0开始的正整数数组w,其中w[i]代表第i个下标的权重。请你实现一个函数pickIndex,它可以随机地从范围[0,w.length-1]内(含0和w.length-1)选出并返回一个下标。选取下标i的概率为w[i]/sum(w)。例如,对于w=[1,3],挑选下标0的概率......
  • 从《老鼠进洞》开始,浅谈模拟费用流
    部分内容来自WC2018PPT。另外,我真的是浅谈。前置知识在学习一下的内容之前,你需要至少学会费用流相关概念,反悔贪心相关概念和堆。当然了,你还要有足够学会模拟费用流的OI基础,因为本文会略去一部分比较trivial的道理。老鼠进洞(其一)有\(n\)个老鼠\(n\)个洞,每只老鼠向......
  • 面试官:做过支付资产?那先聊聊热点账户吧
    背景当前形势不佳,在这种情况下。小猫更是雪上加霜,他被裁了。投了个把月简历,终于约到一个面试。面试官翻了一下简历:“看你简历上写了支付和账户相关项目,那能否聊一下热点账户问题你们是咋处理的吧”。小猫懵逼了一会,“额?什么是热点账户?我们好像模型里面就一个资产账户,然后充值的......
  • 2023.12.31模拟赛总结
    前言:这次还行,今年的最后一场比赛,300pts,rank4T1赛时摆烂了,没有牢记“正难则反”,打了暴力,还挂了正解从后往前考虑,考虑在这个点对后面的点的影响,发现就是p乘上了一个系数,直接从后往前算的时候乘上即可,最后再考虑初始的wT2发现取权值连续的一段数一定是最优的,随便维护一下即可T3......
  • 像Google SRE一样OnCall【转载】
    在GoogleSRE的著作《Google运维解密》[1](原作名:SiteReliabilityEngineering:HowGoogleRunsProductionSystems)中,GoogleSRE的关键成员们几乎不惜用了三个章节的篇幅描述了在Google他们是如何OnCall的。GoogleSRE实践中,有一个广为人知的理念:减少琐事,用软件工程......
  • 二叉树面试题解析
    二叉树面试题解析判断相同的树/***Definitionforabinarytreenode.*publicclassTreeNode{*intval;*TreeNodeleft;*TreeNoderight;*TreeNode(){}*TreeNode(intval){this.val=val;}*TreeNode(intval,TreeNode......
  • 面试官:做过支付资产?那先聊聊热点账户吧
    背景当前形势不佳,在这种情况下。小猫更是雪上加霜,他被裁了。投了个把月简历,终于约到一个面试。面试官翻了一下简历:“看你简历上写了支付和账户相关项目,那能否聊一下热点账户问题你们是咋处理的吧”。小猫懵逼了一会,“额?什么是热点账户?我们好像模型里面就一个资产账户,然后充值的......
  • Python调用 "keybd_event" API模拟按键
    在Python中,可以使用ctypes库来调用WindowsAPI,实现对Windows系统的底层操作。本文将以模拟按键操作(ctrl+v)为例,详细讲解如何在Python中调用WindowsAPI。1.导入ctypes库ctypes是Python的一个外部函数库,它提供了丰富的数据类型,便于调用DLL或共享库中的函数。......
  • 指针面试(避坑题)
    1.强转后类型+1 物理地址+强转后的类型大小个字节#define_CRT_SECURE_NO_WARNINGS1#include<stdio.h>intmain(){ intarr[]={1,2,3,4,5}; short*p=(short*)arr;//将arr强转为short*型,此时每+1, //跳过两个字节,累计四个字节才是一个元素 inti=0; for(i=0;......