某大厂笔试(小*的车站的最近距离)

news2024/12/30 3:48:17

       有一个环形的公路,上面共有n站,现在给定了顺时针第i站到第i+1站之间的距离(特殊的,也给出了第n站到第1站的距离),小*想着沿着公路第x站走到第y站,她想知道最短的距离是多少?

输入描述:

第一行输入一个正整数n,代表站的数量。第二行输入n个正整数ai,前 n-1个数代表顺时针沿看公路走,i站到第i+1站之间的距离:最后一个正整数代表顺时针沿着公路走,第n站到第1 站的距离

第三行输入两个正整数x和y,代表小美的出发地和目的地。

                       1 <=n <=10^5 

                       1<=ai < 10^9

                       1<=x,y<=n

输入:

                   3

                   1 2 2

                   2 3

输出:

                    2

       大厂的笔试永远这么晦涩难懂?刚看到题的时候只能知道它是一道图论问题,题目描述的确实有一点绕,现在让我们来分析一波题的含义:

      假如你现在在车站1,假如你的目的地是车站3,你选择哪条路路径最短?毫无疑问肯定是由车站1直接到车站3路径是最短的,我们可以用眼睛直接观察出来,可是计算机可不能直接得出正确答案?如果你做图论的相关题较多的话,其实你刚看到这道题,心里便会想到这道题,和这题类似的leetcode原题(K 站中转内最便宜的航班),我们今天以讲解leetcode为例,这道题知识稍微在那道题中做了变形就出来了

有 n 个城市通过一些航班连接。给你一个数组 flights ,其中 flights[i] = [fromi, toi, pricei] ,表示该航班都从城市 fromi 开始,以价格 pricei 抵达 toi

现在给定所有的城市和航班,以及出发城市 src 和目的地 dst,你的任务是找到出一条最多经过 k 站中转的路线,使得从 src 到 dst 的 价格最便宜 ,并返回该价格。 如果不存在这样的路线,则输出 -1

n = 3, edges = [[0,1,100],[1,2,100],[0,2,500]]
src = 0, dst = 2, k = 1
输出: 200
解释: 
城市航班图如下:


 

 其实K站中转内最便宜的航班其实约束条件更多一点,其要找到一条最多经过k站中转的路线

我们这次使用递归来解决这个问题

 由于题目中给出我们这些信息,所以我们就可以根据这些信息去构建邻接表:

          因为我们函数在递归的时候,函数中的参数是我们的起点位置,所以我们因为构造一个to-[from,price]的邻接矩阵

//邻接表的数据结构 
Map<Integer,List<Integer[]>> map=new HashMap<>();
  //遍历每一个数组,取出对应的元素
  for(int[] f:flights){
           //起点
           int from=f[0];
           //终点
           int to=f[1];
           //两点之间的距离
           int price=f[2];
           //如果不包含
           if(!map.containsKey(to)){
               map.put(to,new LinkedList<>());
           }
          //构建邻接表
           map.get(to).add(new Integer[]{from,price});
       }

接下来就是我们寻找起点和终点的最短路径的最短距离

函数标签

//dst指的是当前点   k指的是剩下可以步数
private int dfs(int dst, int k) {}

如果我们的起点正好等于我们的终点,直接返回0(说明已经找到了一条可以到达目的地的路线)

 if(dst==src){
      return 0;
    }

如果k==0,说明当前已经不满足题目的要求(没到终点且步数为0),直接返回-1

  if(k==0){
       return -1;
        }

 如果当前节点合法,那么就遍历与它直接相邻的节点

 if(map.containsKey(dst)){
            //遍历邻接表
            for(Integer[] v:map.get(dst)){
                //起点
                int from=v[0];
                //所需要的花费
                int price=v[1];
                //递归下一个节点
                int sub=dfs(from,k-1);
                //如果sub不是-1,就说明该路线是合法的
                if(sub!=-1){
                    //当前节点距离终点的路径=下一个节点距离终点的路径+当前节点距离下一个节点的距离
                    res=Math.min(res,sub+price);
                }
            }
          return res;
        }

这种递归的方法肯定是超时,所以我们使用记忆化搜索的方式去进行优化

 int[][]memo;
 memo=new int[n][k+1];
//如果曾经已经计算过,直接返回答案
if(memo[dst][k]!=-88)return memo[dst][k];
 res= res==Integer.MAX_VALUE?-1:res;
        memo[dst][k]=res;

 

动态规划方式就先不做介绍了,大家下去可以自行试一试

源码如下:

    Map<Integer,List<Integer[]>> map=new HashMap<>();
    //记忆化数组
    int[][]memo;
    //起点
    int src;
    //终点
    int dst;
    public int findCheapestPrice(int n, int[][] flights, int src, int dst, int k) {
        this.dst=dst;
        this.src=src;
        //k表示的节点,我们将结点转换成步数,更利于计算
        k++;
        memo=new int[n][k+1];
        //对记忆化数组进行初始化
        for(int[] row:memo){
            Arrays.fill(row,-88);
        }
       //构造邻接表
       for(int[] f:flights){
           int from=f[0];
           int to=f[1];
           int price=f[2];
           if(!map.containsKey(to)){
               map.put(to,new LinkedList<>());
           }
           map.get(to).add(new Integer[]{from,price});
       }
       return dfs(dst,k);
    }
    //表示从dst的走k步的最小价格
    private int dfs(int dst, int k) {
        if(dst==src){
            return 0;
        }
        if(k==0){
            return -1;
        }
        if(memo[dst][k]!=-88)return memo[dst][k];
        int res=Integer.MAX_VALUE;
        if(map.containsKey(dst)){
            for(Integer[] v:map.get(dst)){
                int from=v[0];
                int price=v[1];
                int sub=dfs(from,k-1);
                if(sub!=-1){
                    res=Math.min(res,sub+price);
                }
            }
        }
       res= res==Integer.MAX_VALUE?-1:res;
        memo[dst][k]=res;
        return memo[dst][k];
    }

       我们再来看这道所谓大厂的笔试题:这道题过程跟这个题一模一样,我们只需要将上面这个题中的k这个约束给省略掉,这道题也就出来了

代码如下:

 Map<Integer,List<Integer[]>> map=new HashMap<>();
    int[]memo;
    int src;
    int dst;
    public int findCheapestPrice(int n, int[][] flights, int src, int dst) {
        this.dst=dst;
        this.src=src;
        memo=new int[n];
        Arrays.fill(memo,-88);
        for(int[] f:flights){
            int from=f[0];
            int to=f[1];
            int price=f[2];
            if(!map.containsKey(to)){
                map.put(to,new LinkedList<>());
            }
            map.get(to).add(new Integer[]{from,price});
        }
        return dfs(dst);
    }

    private int dfs(int dst) {
        if(dst==src){
            return 0;
        }
        if(memo[dst]!=-88)return memo[dst];
        int res=Integer.MAX_VALUE;
        if(map.containsKey(dst)){
            for(Integer[] v:map.get(dst)){
                int from=v[0];
                int price=v[1];
                int sub=dfs(from);
                if(sub!=-1){
                    res=Math.min(res,sub+price);
                }
            }
        }
        res= res==Integer.MAX_VALUE?-1:res;
        memo[dst]=res;
        return memo[dst];
    }

知识ACM模式下我们的所有参数都需要我们手动的去输入,这点也是比较关键点的因素:

起先我是这样写的:

Scanner scanner=new Scanner(System.in);
        int n=scanner.nextInt();
        int[][] nums=new int[n][3];
        int index=0;
        //遍历每个数组
        for(int[] num:nums){
            while(scanner.hasNextInt()){
                //给每个数组进行赋值
                for(int i=0;i<num.length;i++) {
                    if(i==n-1){
                        num[0]=i;
                        num[1]=0;
                        num[2]=scanner.nextInt();
                    }else{
                        num[0]=i;
                        num[1]=i+1;
                        num[2]=scanner.nextInt();
                    }
                }
                break;
            }
        }
        int start=scanner.nextInt();
        int end=scanner.nextInt();

       最后半天一直在死循环,后来发现,每个数组就3个元素,我这个for循环加的位置明显就有问题,所以一直在死循环,所以果断换了一种方式,及时止损

        Scanner scanner = new Scanner(System.in);
        System.out.print("输入行数:");
        int n = scanner.nextInt();
        int m = 3;
        int[][] nums = new int[n][m];
        System.out.println("输入二维数组中的值:");
        //利用双层for循环进行定点输入
        for (int i = 0; i < n; i++) {
            for (int j = 0; j < m; j++) {
                nums[i][j] = scanner.nextInt();
            }
        }
        System.out.println("输入的二维数组为:");
        for (int i = 0; i < n; i++) {
            for (int j = 0; j < m; j++) {
                System.out.print(nums[i][j] + " ");
            }
            System.out.println();
        }
        int start = scanner.nextInt();
        int end = scanner.nextInt();

我们将测试案例试一试:

        这样很明显示我们手动的输入了数组中的元素,这样很显然是不符合题意的,那么我们这么样输入[1 2 2] 会自动生成[[0,1,1],[1,2,2],[2,0,3]]这个数组呢?我们先来说明它这个数组是是怎么生成的?

 因为我们的数组是从0开始计数的,所以我们应该写成这样

 我们开始ACM输入:

 System.out.println("输入二维数组中的值:");
       //输入一行时ACM输入
        while(scanner.hasNextInt()){
            for(int i=0;i<n;i++){
                int dist=scanner.nextInt();
                //如果是最后一个直接指向第一个节点
                if(i==n-1){
                    int[] num=nums[i];
                    num[0]=i;
                    num[1]=0;
                    num[2]=dist;
                 //不是第一个直接指向后一个节点
                }else{
                    int[] num=nums[i];
                    num[0]=i;
                    num[1]=i+1;
                    num[2]=dist;
                }
           }
            //这个break记得加,要不就会死循环
            break;
      }
        System.out.println("输入的二维数组为:");
        for (int i = 0; i < n; i++) {
            for (int j = 0; j < m; j++) {
                System.out.print(nums[i][j] + " ");
            }
            System.out.println();
        }

 

       最后我们这道题也就讲解完了,ACM输入的时候对于很多笔试经验少的同学确实是一个挑战,希望大家刷题的过程中多使用ACM刷题,leetcode的话尽量脱离有提示的工具,最好在网页上进行写

ACM源代码输入:

      Scanner scanner = new Scanner(System.in);
        System.out.print("输入行数:");
        int n = scanner.nextInt();
        int m = 3;
        int[][] nums = new int[n][m];
        System.out.println("输入二维数组中的值:");
        while(scanner.hasNextInt()){
            for(int i=0;i<n;i++){
                int dist=scanner.nextInt();
                if(i==n-1){
                    int[] num=nums[i];
                    num[0]=i;
                    num[1]=0;
                    num[2]=dist;
                }else{
                    int[] num=nums[i];
                    num[0]=i;
                    num[1]=i+1;
                    num[2]=dist;
                }
           }
            break;
      }
        System.out.println("输入的二维数组为:");
        for (int i = 0; i < n; i++) {
            for (int j = 0; j < m; j++) {
                System.out.print(nums[i][j] + " ");
            }
            System.out.println();
        }
        int start = scanner.nextInt();
        //输入的是起点为1,数组的起点为0,所以需要减1
        start=start-1;
        int end = scanner.nextInt();
        end=end-1;

如果有更高的ACM输入的方式或者是解题更妙的技巧,欢迎大家来评论区进行评论!!!

 

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/868341.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

无涯教程-Perl - print函数

描述 此函数将LIST中的表达式的值打印到当前的默认输出文件句柄或FILEHANDLE指定的句柄中。 如果设置,则$\变量将添加到LIST的末尾。 如果LIST为空,则打印$_中的值。 print接受一个值列表,列表中的每个元素都将被解释为一个表达式。 语法 以下是此函数的简单语法- print…

谷歌发布多平台应用开发神器:背靠 AI 编程神器 Codey,支持 React、Vue 等框架,还能代码补全

一、概述 8 月 8 日&#xff0c;谷歌宣布推出 AI 代码编辑器 IDX&#xff0c;旨在提供基于浏览器的人工智能开发环境&#xff0c;用于构建全栈网络和多平台应用程序。谷歌在创建 IDX 时并没有构建新的 IDE&#xff08;集成开发环境&#xff09;&#xff0c;而是使用 VS Code 作…

网络安全(黑客)自学路线/笔记

想自学网络安全&#xff08;黑客技术&#xff09;首先你得了解什么是网络安全&#xff01;什么是黑客&#xff01; 网络安全可以基于攻击和防御视角来分类&#xff0c;我们经常听到的 “红队”、“渗透测试” 等就是研究攻击技术&#xff0c;而“蓝队”、“安全运营”、“安全…

代码随想录算法训练营第55天|动态规划part12|309.最佳买卖股票时机含冷冻期、714.买卖股票的最佳时机含手续费、总结

代码随想录算法训练营第55天&#xff5c;动态规划part12&#xff5c;309.最佳买卖股票时机含冷冻期、714.买卖股票的最佳时机含手续费、总结 309.最佳买卖股票时机含冷冻期 309.最佳买卖股票时机含冷冻期 思路&#xff1a; 区别在第i天持有股票的当天买入的情况&#xff0c…

【Kubernetes】神乎其技的K8s到底是什么,为什么被越来越多人使用

&#x1f680;欢迎来到本文&#x1f680; &#x1f349;个人简介&#xff1a;陈童学哦&#xff0c;目前学习C/C、算法、Python、Java等方向&#xff0c;一个正在慢慢前行的普通人。 &#x1f3c0;系列专栏&#xff1a;陈童学的日记 &#x1f4a1;其他专栏&#xff1a;CSTL&…

户外骨传导耳机推荐,盘点最适合户外佩戴的五款耳机

现在天气越来越暖和了&#xff0c;很多人选择外出徒步、越野或者骑行&#xff0c;在这些活动中往往都会搭配一个骨传导耳机&#xff0c;来让运动过程变得更加有趣。在选购骨传导耳机时&#xff0c;人们通常会考虑音质、舒适性、价格等因素&#xff0c;为了让大家选到更适合自己…

Kafka API与SpringBoot调用

文章目录 首先需要命令行创建一个名为cities的主题&#xff0c;并且创建该主题的订阅者。 1、使用Kafka原生API1.1、创建spring工程1.2、创建发布者1.3、对生产者的优化1.4、批量发送消息1.5、创建消费者组1.6 消费者同步手动提交1.7、消费者异步手动提交1.8、消费者同异步手动…

yolov5目标检测多线程Qt界面

上一篇文章&#xff1a;yolov5目标检测多线程C部署 V1 基本功能实现 mainwindow.h #pragma once#include <iostream>#include <QMainWindow> #include <QFileDialog> #include <QThread>#include <opencv2/opencv.hpp>#include "yolov5.…

phpspreadsheet excel导入导出

单个sheet页Excel2003版最大行数是65536行。Excel2007开始的版本最大行数是1048576行。Excel2003的最大列数是256列&#xff0c;2007以上版本是16384列。 xlswriter xlswriter - PHP 高性能 Excel 扩展&#xff0c;功能类似phpspreadsheet。它能够处理非常大的文件&#xff0…

056B R包ENMeval教程-基于R包ENMeval对MaxEnt模型优化调参和结果评价制图(更新)

056B-1 资料下载 056B-2 R包ENMeval在MaxEnt模型优化调参中的经典案例解读 056B-3 R软件和R包ENMeval工具包安装 056B-4 R软件和R包ENMeval安装报错解决办法 056B-5 环境数据格式要求和处理流程 056B-6 分布数据格式要求和处理流程 056B-7 基于R包ENMeval对MaxEnt模型优化…

12.pod生命周期和存储卷

文章目录 pod生命周期pod启动阶段故障排除步骤&#xff1a; 存储卷emptyDir存储卷 hostPath存储卷nfs共享存储卷总结&#xff1a; pod生命周期 pod启动阶段 一般来说&#xff0c;pod 这个过程包含以下几个步骤&#xff1a; 调度到某台 node 上。kubernetes 根据一定的优先级算…

【C#】静默安装、SQL SERVER静默安装等

可以通过cmd命令行来执行&#xff0c;也可以通过代码来执行&#xff0c;一般都需要管理员权限运行 代码 /// <summary>/// 静默安装/// </summary>/// <param name"fileName">安装文件路径</param>/// <param name"arguments"…

Dubbo 2.7.0 CompletableFuture 异步

了解Java中Future演进历史的同学应该知道&#xff0c;Dubbo 2.6.x及之前版本中使用的Future是在java 5中引入的&#xff0c;所以存在以上一些功能设计上的问题&#xff0c;而在java 8中引入的CompletableFuture进一步丰富了Future接口&#xff0c;很好的解决了这些问题。 Dubb…

小内存嵌入式设备软件的差分升级设计(学习)

摘要 提出一种改进HDiffPatch算法并在复旦微单片机上实现小内存差分升级的方案&#xff0c;即使用单片机内的Flash空间替代算法占用的RAM空间&#xff0c;从而减少算法对单片机RAM空间的需求&#xff0c;以满足小内存微处理器的差分升级&#xff0c;同时对算法内存分配释放函数…

HashMap源码探究之底“库”看穿

前言&#xff1a; 本次的源码探究会以jdk1.7和jdk1.8对比进行探究二者在HashMap实现上有的差异性&#xff0c;除此之外&#xff0c;还会简单介绍HashMap的hash算法的设计细节、jdk1.8中HashMap添加功能的整个流程、什么情况下会树化等源码设计知识。 一、HashMap介绍 HashMap…

SpringBoot3数据库集成

标签&#xff1a;Jdbc.Druid.Mybatis.Plus&#xff1b; 一、简介 项目工程中&#xff0c;集成数据库实现对数据的增晒改查管理&#xff0c;是最基础的能力&#xff0c;而对于这个功能的实现&#xff0c;其组件选型也非常丰富&#xff1b; 通过如下几个组件来实现数据库的整合…

Spring Cloud 智慧工地源码(PC端+移动端)项目平台、监管平台、大数据平台

智慧工地源码 智慧工地云平台源码 智慧建筑源码 “智慧工地”是利用物联网、人工智能、云计算、大数据、移动互联网等新一代信息技术&#xff0c;彻底改变传统建筑施工现场参建各方现场管理的交互方式、工作方式和管理模式&#xff0c;实现对人、机、料、法、环的全方位实时监…

uniapp开发公众号,微信开发者工具进行本地调试

每次修改完内容都需要发行之后&#xff0c;再查看效果&#xff0c;很麻烦 &#xff01;&#xff01;&#xff01; 下述方法&#xff0c;可以一边在uniapp中修改内容&#xff0c;一边在微信开发者工具进行本地调试 修改hosts文件 在最后边添加如下内容 修改前端开发服务端口 …

Android 第一行代码学习 -- 聊天界面小练习

前言&#xff1a;最近在学习安卓&#xff0c;阅读入门书籍第一行代码&#xff0c;以后更新的知识可能大部分都会和安卓有关。 实现聊天界面 1.编写主界面 个人觉得界面编写刚开始学可能看着很乱&#xff0c;但是其中最重要的是层次&#xff0c;看懂了其中的层次&#xff0c;就…

论element-ui表格的合并行和列(巨细节)

论element-ui表格的合并行和列 0、前言 ​ 作为一个后端来写前端属实是痛苦、讲真的、刚开始我是真不想用饿了么的这个合并行和列、因为太语焉不详了、看着头疼、后来发现好像我没得选、只好硬着头皮上了。 1、element - ui 的合并行和列代码 效果图&#xff1a; 代码&…