LeetCode 1138. 字母板上的路径

题目描述

解题思路:

思路是维护两个坐标,分别为当前位置坐标和下一个目标位置坐标。假设下一个目标字符为c,则下一个目标位置坐标的横坐标为x = (c-‘a’) / 5, y = (c-‘a’) % 5;

有了上述两个坐标,我们就可以得到一个向量,从当前坐标指向目标坐标,且由题意可知,只有上下左右四个方向可以运动,因此最快的方式肯定是要么横向一直朝着左或右走,纵向一直朝着上或下走,同时横向移动和纵向移动的顺序可以随意。因此最短的移动方式有多重,这里我采用的是横着或纵着走到底。

本题还还有一个坑的地方,就是最后一个字符‘z’所处的位置,它是特殊的,除去它不看,正好是5 * 5 的方阵,加上它之后,假设target为‘zb’,那么按照上述的策略就会存在走出边界的情况,因此上述策略是不完善的,需要改善。

根据观察,我采取的解决办法是,算出上述向量的竖直方向上的分量,如果这个分量的方向是向上的,说明走向整体是向上的,当在除去‘z’的5 * 5方阵中移动时,上述策略不会有问题;当将‘z’考虑进来后,我是采用先在竖直方向上移动,然后再在水平方向上移动的策略来避免出界的。同理向竖直方向上的分量是向下的,说明走向整体是向下移动,当target为“z”,这种情况时,之前的策略会出界,我的改进策略是先让其横向移动,然后再纵向移动。

综上所述,我的改进思路就是根据情况改变先横走还是先纵走的顺序,因此代码上应该抽象出一个“移动”方法,该方法可以根据入参来判断是横走还是纵走。 具体代码如下:

class Solution {
    public String alphabetBoardPath(String target) {
        char[] tc = target.toCharArray();
        StringBuilder sb = new StringBuilder();

        int curX = 0, curY = 0;
        for(int i = 0; i < tc.length; i++) {
            int tarX = (tc[i]-'a') / 5, tarY = (tc[i] - 'a') % 5;

            int distanceX = tarY - curY;
            char c1 = distanceX>=0 ? 'R' : 'L';

            int distanceY = tarX - curX;
            char c2 = distanceY>=0 ? 'D' : 'U';

            if(distanceY > 0) {
                //当整体位移方向是向下时,采取先走横再走纵的策略来避免走出边界
                go(sb, distanceX, c1);
                go(sb, distanceY, c2);
            }else {
                //当整体位移方向是向上是,采取先走纵再走横的策略来避免走出边界
                go(sb, distanceY, c2);
                go(sb, distanceX, c1);
            }

            //到达目标位置
            sb.append('!');

            //更新当前坐标
            curX = tarX; curY = tarY;
        }

        return sb.toString();
    }

    //移动方法
    //distance: 移动距离
    //c: 横移还是纵移
    private void go(StringBuilder sb, int distance, char c) {
        distance = distance<0 ? -distance : distance;
        for(int j = 0; j < distance; j++) {
            sb.append(c);
        }
    }

}

image.png

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值