JAVA程序设计:检查字符串是否可以通过排序子字符串得到另一个字符串(LeetCode:5514)

给你两个字符串 s 和 t ,请你通过若干次以下操作将字符串 s 转化成字符串 t :

选择 s 中一个 非空 子字符串并将它包含的字符就地 升序 排序。
比方说,对下划线所示的子字符串进行操作可以由 "14234" 得到 "12344" 。

如果可以将字符串 s 变成 t ,返回 true 。否则,返回 false 。

一个 子字符串 定义为一个字符串中连续的若干字符。

 

示例 1:

输入:s = "84532", t = "34852"
输出:true
解释:你可以按以下操作将 s 转变为 t :
"84532" (从下标 2 到下标 3)-> "84352"
"84352" (从下标 0 到下标 2) -> "34852"
示例 2:

输入:s = "34521", t = "23415"
输出:true
解释:你可以按以下操作将 s 转变为 t :
"34521" -> "23451"
"23451" -> "23415"
示例 3:

输入:s = "12345", t = "12435"
输出:false
示例 4:

输入:s = "1", t = "2"
输出:false
 

提示:

s.length == t.length
1 <= s.length <= 105
s 和 t 都只包含数字字符,即 '0' 到 '9' 。

思路:对于这类题,我们考虑从反面思考求解,也就是找有哪些情况会导致s串无法变换到t串。对于一个数,我们知道按照题目要求的操作,它可以往前移动几位取决于该位置前有多少个比它大的数,同理该位置后面有多少个比它小的数,它最多就能往后移动几位。我们考虑从后往前遍历t字符串,对于当前遍历到的字符,因为该字符的最终位置是确定的, 因此通过位置i来判断出false只有两种情况:

①s串中同样的字符已经没有了。

②s串中同样的字符无法移动到位置i,这种情况我们需要想办法快速判断,我们可以首先找到t中位置i上的字符在s中当前最后一次出现的位置,我们需要保证这个字符一定可以往后移动到位置i,因此就要满足所有比该字符大的字符的位置都要出现在该字符之后。这一过程我们可以采用栈来模拟。

class Solution {
    public boolean isTransformable(String s, String t) {

        int n = s.length();
        Stack[] st = new Stack[10];

        for (int i = 0; i < 10; i++)
            st[i] = new Stack<>();

        for (int i = 0; i < n; i++)
            st[s.charAt(i) - '0'].add(i);

        for (int i = n - 1; i >= 0; i--) {
            int now = t.charAt(i) - '0';
            if (st[now].isEmpty()) return false;
            for (int j = now + 1; j < 10; j++)
                if (!st[j].isEmpty() && st[now].peek() < st[j].peek())
                    return false;
            st[now].pop();
        }

        return true;

    }
}

 

你可能感兴趣的:(JAVA程序设计:检查字符串是否可以通过排序子字符串得到另一个字符串(LeetCode:5514))