• [LeetCode 1585] Check If String Is Transformable With Substring Sort Operations


    Given two strings s and t, you want to transform string s into string t using the following operation any number of times:

    • Choose a non-empty substring in s and sort it in-place so the characters are in ascending order.

    For example, applying the operation on the underlined substring in "14234" results in "12344".

    Return true if it is possible to transform string s into string t. Otherwise, return false.

    A substring is a contiguous sequence of characters within a string.

     

    Example 1:

    Input: s = "84532", t = "34852"
    Output: true
    Explanation: You can transform s into t using the following sort operations:
    "84532" (from index 2 to 3) -> "84352"
    "84352" (from index 0 to 2) -> "34852"
    

    Example 2:

    Input: s = "34521", t = "23415"
    Output: true
    Explanation: You can transform s into t using the following sort operations:
    "34521" -> "23451"
    "23451" -> "23415"
    

    Example 3:

    Input: s = "12345", t = "12435"
    Output: false
    

    Example 4:

    Input: s = "1", t = "2"
    Output: false
    

     

    Constraints:

    • s.length == t.length
    • 1 <= s.length <= 105
    • s and t only contain digits from '0' to '9'.

    Solution 1.

    Since we can only sort any substring in ascending order, when s[i] != t[i], if the next available character t[i] in s is at index j(j > i), then it must be true that all the characters in between index i + 1 and j - 1 are bigger than t[i]. Otherwise, it'd be impossible to change s[i] to t[i]. Using this observation, we derive the following greedy algorithm.

     

    1. store all digits' index in order for start string s. 

    2. keep track of current arrangement count for all digits 0 to 9 for target string t. 

    3. loop over t from left to right, and do the following checks:

    a. for the current character C in t, check if we've already used all available C from s. If so, it means t has more C than s, s and t are not anagram, return false;

    b. for characters smaller than C, check if their next available indices are after the next available C's index. If not, it means there is at least one smaller character before the next available C, C can never be swapped to the current t's position, return false.

    c. if all checks for each position pass, return true.

     

    Both the runtime and space complexity is O(N).

    class Solution {
        public boolean isTransformable(String s, String t) {
            int n = s.length();
            List<Integer>[] sIdx = new List[10];
            for(int i = 0; i < 10; i++) {
                sIdx[i] = new ArrayList<>();
            }
            for(int i = 0; i < n; i++){
                sIdx[s.charAt(i) - '0'].add(i);
            }
            int[] tCnt = new int[10];
            for(int i = 0; i < n; i++) {
                int d = t.charAt(i) - '0';
                if(tCnt[d] >= sIdx[d].size()) {
                    return false;
                }
                for(int j = 0; j < d; j++) {
                    if(tCnt[j] < sIdx[j].size() && sIdx[j].get(tCnt[j]) < sIdx[d].get(tCnt[d])) {
                        return false;
                    }
                }
                tCnt[d]++;
            }
            return true;
        }
    }

    Solution 2.

    There is another elegant O(N) solution.  The key idea is that when checking each digit in s from left to right, we map each digit to its correct position in t. At position i, if s[i] is mapped to position j in t, then we know for all positions > i with bigger digits than s[i],  the furthest left they can go is j + 1 as they can not go pass left of s[i]'s mapped position j. So we create the mapping of all digits from s to t, then check if each digits in s meet this left bound condition. Each time we confirm a mapping at a position, we also update the bigger digits' left bound constraints.

    class Solution {
        public boolean isTransformable(String s, String t) {
            int n = s.length();
            Deque<Integer>[] idx = new ArrayDeque[10];
            //idx[i]: digit i's index in ascending order in string t
            for(int i = 0; i < 10; i++) idx[i] = new ArrayDeque<>();
            for(int i = 0; i < n; i++) {
                idx[t.charAt(i) - '0'].addLast(i);
            }
            //mapTo[i]: mapping from position i in s to s[i]'s correct position in t. 
            int[] mapTo = new int[n];
            for(int i = 0; i < n; i++) {
                int d = s.charAt(i) - '0';
                //if the current digit can not be mapped to t, s and t are not anagrams
                if(idx[d].size() == 0) {
                    return false;
                }
                mapTo[i] = idx[d].pollFirst();
            }
            //lBound[i]: the leftMost position(exclusive) that digit i can appear in string t 
            int[] lBound = new int[10];
            for(int i = 0; i < n; i++) {
                //d: current digit in s
                int d = s.charAt(i) - '0';
                //mapTo[i]: current digit's mapped position in t, it can not go to the left of lBound[d]
                if(mapTo[i] < lBound[d]) {
                    return false;
                }
                //current digit may further tighten future bigger digits' leftMost bound, they can not go to
                //the left of mapTo[i] as mapTo[i] represents the furthest right position for digit d int t,
                //all future > d digits can not go pass left of this position
                for(int j = d + 1; j < 10; j++) {
                    lBound[j] = Math.max(lBound[j], mapTo[i]);
                }
            }
            return true;
        }
    }
     
     
  • 相关阅读:
    void*指针的由来
    Linux下的ELF文件格式简介
    通过中断门或陷阱门的转移——【只上传好图一张】
    ELF(Executable and Linking Format)
    call Init8259A——痛定思痛,不要数典忘祖了
    orange's习题——第三章【中断和异常】
    静态库
    可执行文件elf的格式
    谈谈我对攻读计算机研究生的看法
    tips for C
  • 原文地址:https://www.cnblogs.com/lz87/p/13670941.html
Copyright © 2020-2023  润新知