寻友之旅 —— 码上掘金

50 阅读3分钟

当青训营遇上码上掘金

主题 3:寻友之旅

小青要找小码去玩,他们的家在一条直线上,当前小青在地点 N ,小码在地点 K (0≤N , K≤100 000),并且小码在自己家原地不动等待小青。小青有两种交通方式可选:步行和公交。
步行:小青可以在一分钟内从任意节点 X 移动到节点 X-1 或 X+1
公交:小青可以在一分钟内从任意节点 X 移动到节点 2×X (公交不可以向后走)

请帮助小青通知小码,小青最快到达时间是多久?
输入: 两个整数 N 和 K
输出: 小青到小码家所需的最短时间(以分钟为单位)

作者:青训营官方账号
链接:juejin.cn/post/718775…
来源:稀土掘金
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。

解题思路

此题可分为4种情况

  1. 输入的N小于0,K大于100000,不符合题目要求,直接返回-1

  2. 输入的N大于K,因为公交车不能向后行驶,小青故只能步行达到小码家,所使用的时间为(N - K)

  3. 输入的N等于K,小青家与小码家在同一节点,故使用时间为0

  4. 输入的N小于K,最显眼的题目要求,在同一时间上,坐公交比步行快许多,所以我们用一个贪心算法的思想,只坐公交,但是有一个特殊情况,当N为0时,坐公交还是在原地,所以若N为0,则步行一次。之后再坐公交,当在下一次坐公交可以超过K点的距离时,要进行一个判断,若提前下车,步行到K点的时间小于坐公交到超过K点的距离,然后步行返回的时间,则提前下车,否则,坐公交后步行返回。

代码实现

import java.util.*;


public class Main {
   public static void main(String []args) {
                Scanner scanner = new Scanner(System.in);
                int N = scanner.nextInt();
                int K = scanner.nextInt();
                int time = selectRoad(N, K);
                System.out.println(time);
        }


        public static int selectRoad(int N,int K){
                if(N < 0 || K > 100000) {
                        return -1;
                }
                int time = 0;//计数时间
                //如果小码家住在小青家后面,则只能步行
                if(K < N){
                        time = N - K;
                        return time;
                }else if (N == K){//若两个人就住在同一节点,就直接返回0,不用走
                        time = 0;
                        return time;
                }else {//利用贪心算法的思想,时间一样,尽量坐公交,用N的变化来慢慢靠近K
                        while (N < K){
                                //当结点N为0时,只能走路
                                if(N == 0){
                                        N = 1;
                                        time++;
                                        continue;
                                }
                                //如果N不为0就开始坐公交,坐公交到提前一站要考虑是直接坐过,走路回退时间短,还是提前下车走路到达时间短
                                if(N * 2 <= K){
                                       N *= 2;
                                       time++;
                                }else {//如果此时坐公交可以超过了K点,要进行以上注释的考虑
                                        if((K - N) < (N * 2 - K)){//此时可提前下车,走路到K点
                                                time += (K - N);
                                        }else {//
                                                time = time + 1 + (N * 2 - K);
                                        }
                                        N = K;
                                }
                        }
                        return time;
                }
        }
}