当青训营遇上码上掘金之寻友之旅java思想及实现

63 阅读2分钟

*# 当青训营遇上码上掘金*

babdc4fe29cc6ac6b1e91aa5a282766.png 题目:寻友之旅

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

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

思路:

动态规划问题

小青和小码在一条直线上,小青如果步行去小码家,那肯定时间非常长,题目问最快到达时间是多少,那么肯定要添加公交的方式,但是如何去判断在哪坐公交,那一段是步行呢,找到最优问题。

首先维护一个dis[1000000]数组,此为N到达每一个点的最短时间,(相当于一个动态规划数组)然后最初的位置dis[N]=0,其他的位置设置为∞。

找到动态规划的问题状态之间的关系,首先如果到达当前位置x的时间为dis[x],则分为三种情况,步行+1到达,步行-1到达和公交*2到达,则问题可以转化成关系式

如果当前位置x的时间比前一个位置x-1大的话则加1步,dis[x]=dis[x-1]+1,如果当前位置x比后一个位置x+1大的话则减一步,dis[x]=dis[x+1]+1,如果当前位置x*2比步行大的话,则dis[x*2]=dis[x]+1

如何记录当前小青走到什么位置了呢,需要进行什么操作呢,用到了队列queue,(相当于bfs广度优先遍历)使用队列开始从第一个位置N开始行走,当每次都记录三种状态的最短时间,记录每次走的一步的位置,到dis[k]为最小的时间位置。

代码实现:

    public static int mintime(int N,int K) {
        int INF = 100000000;//定义无穷大
        int[] dis = new int[200000];//定义最小值数组
        //初始化最小距离数组
        for (int i = 0; i < dis.length; i++) {
            dis[i] = INF;
        }
        dis[N] = 0;
        //初始化队列
        Queue<Integer> queue = new LinkedList<Integer>();
        queue.add(N);
        while (!queue.isEmpty()) {
            int x = queue.poll();
            if (x > K) {
                if (dis[K] > dis[x] + x - K) {
                    dis[K] = dis[x] + x - K;
                }
            } else {
                if (dis[x + 1] > dis[x] + 1) {
                    dis[x + 1] = dis[x] + 1;
                    queue.add(x + 1);
                }
                if (x > 0) {
                    if (dis[x - 1] > dis[x] + 1) {
                        dis[x - 1] = dis[x] + 1;
                        queue.add(x - 1);
                    }

                    if (x > 1 && dis[x * 2] > dis[x] + 1) {
                        dis[x * 2] = dis[x] + 1;
                        queue.add(x * 2);
                    }
                }
            }

        }
        retuen dis[K];
    }
}

[具体的代码实现请看](java实现小青找小码 - 码上掘金 (juejin.cn))