zoukankan      html  css  js  c++  java
  • [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;
        }
    }
     
     
  • 相关阅读:
    Linux 内核源码中likely()和unlikely()【转】
    详解likely和unlikely函数【转】
    [arm驱动]Linux内核开发之阻塞非阻塞IO----轮询操作【转】
    Linux时间子系统之六:高精度定时器(HRTIMER)的原理和实现【转】
    Linux下的hrtimer高精度定时器【转】
    Linux 高精度定时器hrtimer 使用示例【转】
    Linux 进程等待队列【转】
    【转】【Android】对话框 AlertDialog -- 不错不错
    【转】 CATransform3D 矩阵变换之立方体旋转实现细节
    【转】如何在IOS中使用3D UI
  • 原文地址:https://www.cnblogs.com/lz87/p/13670941.html
Copyright © 2011-2022 走看看