【LeetCode - 249】移位字符串分组

1、题目描述

在这里插入图片描述

2、解题思路

  定义一个辅助方法 isShifted(String s, String t) 表示字符串 s 是否可以通过移位变为 t。

  1、如果 s 和 t 长度不一致,肯定无法通过移位进行转换,返回 false;

  2、如果 s 和 t 长度一致,且长度为 1,则肯定可以移位转换;

  3、如果 s 和 t 长度一致且不为 1,则可以移位进行转换的判断是 s 的每一个字符都移动相同的步数变为 s。

  例如:“abc” 的每一个字符移动 3 次变为 “def”。而 “abc” 无法经过统一的步数变为 “dkz”。

  有了 isShifted(String s, String t) 方法,则问题变得很简单:

  1、遍历字符串数组;

  2、如果 strings[i] 已经被使用过了,则跳过;如果没有被使用过,添加到 List 中;

  3、从 [i+1, strings.length-1] 中找到 isShifted(strings[i], strings[j]) 为 true 的添加到 List 中,并把 strings[j] 设置为已使用。

  4、返回 List 的总和。

3、解题代码

class Solution {
    public List<List<String>> groupStrings(String[] strings) {
        List<List<String>> ans = new ArrayList<>();
        boolean[] isAdded = new boolean[strings.length];
        for (int i = 0; i < strings.length; i++) {
            List<String> list = new ArrayList<>();
            if (isAdded[i]) {
                /// 如果该字符串已经添加,则跳过
                continue;
            } else {
                // 该字符串没被添加,则加入到 list
                list.add(strings[i]);
            }
            // 找到 strings[i] 的所有移位,并添加到 list 中
            for (int j = i + 1; j < strings.length; j++) {
                // 第 j 个字符串没有添加过,且 strings[i] 可以移位变为 strings[j]
                if (!isAdded[j] && isShifted(strings[i], strings[j])) {
                    list.add(strings[j]);
                    isAdded[j] = true;
                }
            }
            ans.add(list);
        }
        return ans;
    }

    /**
     * s 可以移位变为 t
     *
     * @param s
     * @param t
     * @return
     */
    private boolean isShifted(String s, String t) {
        if (s.length() != t.length()) return false; // 长度不相同,肯定不能移位 s 变为 t
        if (s.length() == 1) return true;   // 长度相同,且长度为 1,可以移位 s 变为 t
        int gap = 0;    // 字符串相邻字符的间隔,如:ab 的间隔为
        int differ = t.charAt(0) - s.charAt(0);
        if (differ < 0) {
            // 比如 t[0] == 'b', s[0] == 'a',则 'b' - 'a' = -1
            // 26 + (-1) = 25,可以看成 'b' 移位了 25 次变为 'a'
            gap = 26 + differ;
        } else {
            gap = differ;
        }
        for (int i = 0; i < s.length(); i++) {
            int curgap = 0; // 当前间隔
            int curDiffer = t.charAt(i) - s.charAt(i);
            if (curDiffer < 0) {
                curgap = 26 + curDiffer;
            } else {
                curgap = curDiffer;
            }
            if (curgap != gap) {
                // s 和 t 每一个位置的字符间隔应该一致才能通过移位使得 s 变为 t
                // 例如:ab 就无法移位转为 cf,因为 ab 间隔为 1,cf间隔为 3,a-c移位 2 次,b-f移位 4 次
                return false;
            }
        }
        return true;
    }
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值