1. 程式人生 > 實用技巧 >LeetCode 1585 Check If String Is Transformable With Substring Sort Operations

LeetCode 1585 Check If String Is Transformable With Substring Sort Operations

題目

題意:一個只有0-9組成的字串,每次選擇任意一個子串,按照數字從小到大排序。問從源字串能否經過若干次操作轉換成目標字串。

題解:首先題目只問了是否,而沒有問多少次,所以可以判斷出,我們不關心過程是怎麼樣的,只關心結果能否到達。所以不太可能是動態規劃,搜尋什麼的。
既然是看結果,那估計是個找規律的題目。首先看目標字串的第一個字元x,如果它是由源字串的某個字元x經過排序之後,安排到了第一個位置,那麼它一定滿足,在源字串中從起始位置到x的位置的子串中,x一定是最小的那個。否則x就無法移動到第一個位置。
一次內推,第二個字元x2, 由於第一個字元x已經確定了我們把x變成最大值,那麼x2應該滿足從源字串起始位置到x2的位置的子串中,x2是最小的那個。

所以這道題目就變成了單點更新,求區間最值。
使用簡單優雅的資料結構,樹狀陣列,即可解決問題。
樹狀陣列的區間最值,要比區間和複雜一點,且更新的時間效率是Log(n)*Log(n)
跟線段樹比差一點。

class Solution {
public:
    int c[100005];
    int a[100005];
    vector<int> pos[10];
    int n;
    bool isTransformable(string s, string t) {
        
        for(int i = s.length()-1;i>=0;i--)
        {
            int num = s[i]-'0';
            pos[num].push_back(i+1);
        }
        
        n = s.length();
        for(int i=0;i<=n;i++)
        {
            c[i] = INT_MAX;
        }
        
        for(int i=0;i<s.length();i++)
        {
            add(i+1,s[i]-'0');
            a[i+1]=s[i]-'0';
        }
        
        for(int i=0;i<t.length();i++)
        {
            if(pos[t[i]-'0'].size()==0)
                return false;
            int p = pos[t[i]-'0'].back();
            pos[t[i]-'0'].pop_back();
            int m = get(1,p);
            if(m!=t[i]-'0')
                return false;
            
            add(p,INT_MAX);
        }
        
        return true;
        
    }
    
    int lowbit(int x)
    {
        return x&(-x);
    }
    
    void add(int index,int num)
    {
        a[index] = num;
        while(index<=n)
        {
            int l = index-lowbit(index)+1;
            int m = get(l, index-1);
            if(l==index)
            {
                c[index]=a[index];
            }
            else if(min(m, a[index])!=c[index])
            {
                c[index]=min(m, a[index]);
            }
            else
            {
                break;
            } 
            index+=lowbit(index);
        }
    }
    
    int get(int l, int r)
    {
        if(l>r)
            return INT_MAX;
        int ans = INT_MAX;
        while(r>=l)
        {
            if(r-lowbit(r) < l-1)
            {
                ans = min(ans, a[r]);
                r--;
            }
            else
            {
                ans = min(ans, c[r]);
                r-=lowbit(r);
            }
        }
        return ans;
    }
};