LeetCode 1585 Check If String Is Transformable With Substring Sort Operations
阿新 • • 發佈:2020-09-21
題意:一個只有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; } };