1. <strong id="7actg"></strong>
    2. <table id="7actg"></table>

    3. <address id="7actg"></address>
      <address id="7actg"></address>
      1. <object id="7actg"><tt id="7actg"></tt></object>

        01trie 在面試中的妙用

        共 5089字,需瀏覽 11分鐘

         ·

        2021-08-11 23:44

        簡介

        就是把整數(shù)的二進制表達式當(dāng)作字符串,之前寫過一篇字典樹,按照從高位到低位的順序,掛載在字典樹上,每個節(jié)點有兩個孩子,分別是 ,從而形成一棵二叉樹,常用來處理異或問題

        例如將一個數(shù)組 掛在 上,便得到如下所示的一棵二叉樹

        a168adacd5c3b285637e608ca64ae82c.webp

        性質(zhì)

        由于 是一棵二叉樹,且最大深度取決于掛載值的大小,設(shè)掛載最大值為 ,那么一次查詢前綴的過程便可以在 時間完成

        例題

        力扣 421. 數(shù)組中兩個數(shù)的最大異或值

        給定 個正整數(shù)的數(shù)組 ,計算 的最大值

        數(shù)據(jù)規(guī)定

        題解

        將數(shù)組中所有正整數(shù)的二進制表示,按照從高位到低位的順序,當(dāng)作字符串掛載在字典樹上,形成 字典樹,該字典樹為一棵二叉樹

        對于正整數(shù) ,為了尋找數(shù)組中的 ,使得 最大,我們只要每次貪心走與當(dāng)前位相反的路即可

        具體來講,如果當(dāng)前位為 ,我們走 子樹,反之走 子樹,當(dāng)然,如果不存在對應(yīng)的子樹,我們還是得走存在的子樹

        這樣可以保證異或后的高位盡可能為 ,在二進制表示中,高位為 ,即使剩下的全 ,結(jié)果也要比高位為 ,剩下的全 結(jié)果大,直觀的感受,,這便證明了貪心的正確性

        時間復(fù)雜度為 ,其中

        //?cpp
        const?int?N?=?2e4;
        const?int?M?=?31;

        class?Solution?{
        public:
        ????int?node[N?*?M][2],?cnt?=?0;

        ????void?insert(int?x)
        ????
        {
        ????????int?p?=?0;
        ????????for?(int?i?=?M;?i?>=?0;?--i)?{
        ????????????int?idx?=?1?&?(x?>>?i);
        ????????????if?(!node[p][idx])?node[p][idx]?=?++cnt;
        ????????????p?=?node[p][idx];
        ????????}
        ????}
        ????int?query(int?x)
        ????
        {
        ????????int?p?=?0;
        ????????int?ans?=?0;
        ????????for?(int?i?=?M;?i?>=?0;?--i)?{
        ????????????int?idx?=?1?&?(x?>>?i);
        ????????????if?(node[p][idx?^?1])?{
        ????????????????ans?*=?2,?ans?+=?1;
        ????????????????p?=?node[p][idx?^?1];
        ????????????}
        ????????????else?{
        ????????????????ans?*=?2,?ans?+=?0;
        ????????????????p?=?node[p][idx];
        ????????????}
        ????????}
        ????????return?ans;
        ????}

        ????int?findMaximumXOR(vector<int>&?nums)?{
        ????????for?(auto?&i:?nums)?insert(i);
        ????????int?ans?=?0;
        ????????for?(auto?&i:?nums)?ans?=?max(ans,?query(i));
        ????????return?ans;
        ????}
        };

        力扣 1707. 與數(shù)組中元素的最大異或值

        給定 個正整數(shù)的數(shù)組 ,給定 個詢問,每個詢問包含兩個正整數(shù)

        對于每一個詢問,在 中所有不大于 的數(shù)中選一個 ,使得 最大,返回這個最大值

        數(shù)據(jù)規(guī)定

        題解

        離線查詢,對 從小到大排序,對 按照 從小到大排序

        根據(jù)單調(diào)性,使用雙指針,將 中符合條件的正整數(shù) 掛載到字典樹上,進行查詢即可

        時間復(fù)雜度為 ,其中

        //?cpp
        #define?pb?push_back

        const?int?N?=?1e5;
        const?int?M?=?30;

        class?Solution?{
        public:
        ????int?node[N?*?M][2],?cnt?=?0;

        ????void?insert(int?x)
        ????
        {
        ????????int?p?=?0;
        ????????for?(int?i?=?M;?i?>=?0;?--i)?{
        ????????????int?idx?=?1?&?(x?>>?i);
        ????????????if?(!node[p][idx])?node[p][idx]?=?++cnt;
        ????????????p?=?node[p][idx];
        ????????}
        ????}
        ????int?query(int?x)
        ????
        {
        ????????int?p?=?0;
        ????????int?ans?=?0;
        ????????for?(int?i?=?M;?i?>=?0;?--i)?{
        ????????????int?idx?=?1?&?(x?>>?i);
        ????????????if?(node[p][idx?^?1])?{
        ????????????????ans?*=?2,?ans?+=?1;
        ????????????????p?=?node[p][idx?^?1];
        ????????????}
        ????????????else?{
        ????????????????ans?*=?2,?ans?+=?0;
        ????????????????p?=?node[p][idx];
        ????????????}
        ????????}
        ????????return?ans;
        ????}

        ????vector<int>?maximizeXor(vector<int>&?nums,?vector<vector<int>>&?q)?{
        ????????int?idx?=?0;
        ????????for?(auto?&i:?q)?i.pb(idx++);
        ????????sort(q.begin(),?q.end(),?[&](const?vector<int>?&x,?const?vector<int>?&y){
        ????????????return?x[1]?<?y[1];
        ????????});
        ????????sort(nums.begin(),?nums.end());
        ????????int?n?=?q.size();
        ????????vector<int>?ans(n);
        ????????for?(int?i?=?0,?j?=?0;?i?<?n;?++i)?{
        ????????????while?(j?<?nums.size()?&&?nums[j]?<=?q[i][1])
        ????????????????insert(nums[j++]);
        ????????????if?(!j)?ans[q[i][2]]?=?-1;
        ????????????else?ans[q[i][2]]?=?query(q[i][0]);
        ????????}
        ????????return?ans;
        ????}
        };

        力扣 1938. 查詢最大基因差

        給定一棵 個節(jié)點的樹,每個節(jié)點的編號 即為其權(quán)值

        給定 個查詢,每個查詢包含樹上一個點的編號 和目標值

        對于每一個查詢,你需要選一個從根到 的節(jié)點 ,要求使得 值最大,返回這個最大值

        數(shù)據(jù)規(guī)定

        題解

        離線查詢,維護每個節(jié)點的所有查詢

        我們需要維護一個從根到當(dāng)前節(jié)點的路徑,因此考慮 dfs

        具體來講,深搜到當(dāng)前點 時,將 掛載在 01 trie 上,同時進行一次查詢,計算出最大的異或值,繼續(xù)向下深搜,等到回溯的時候,將當(dāng)前節(jié)點的權(quán)值從字典樹上刪除

        計算最大異或值時,每次貪心選擇與當(dāng)前位相反的節(jié)點即可

        時間復(fù)雜度為 ,其中

        //?cpp
        #define?pii?pair<?int,?int?>
        #define?fi?first
        #define?se?second
        #define?pb?push_back

        const?int?N?=?2e5;
        const?int?M?=?18;

        int?node[N?*?M][2],?bucket[N?*?M][2],?cnt?=?0;

        void?insert(int?x)
        {
        ????int?p?=?0;
        ????for?(int?i?=?M;?i?>=?0;?--i)?{
        ????????int?idx?=?1?&?(x?>>?i);
        ????????if?(!node[p][idx])?node[p][idx]?=?++cnt;
        ????????bucket[p][idx]++;
        ????????p?=?node[p][idx];
        ????}
        }
        void?del(int?x)
        {
        ????int?p?=?0;
        ????for?(int?i?=?M;?i?>=?0;?--i)?{
        ????????int?idx?=?1?&?(x?>>?i);
        ????????int?next?=?node[p][idx];
        ????????if?(bucket[p][idx]?==?1)?node[p][idx]?=?0;
        ????????bucket[p][idx]--;
        ????????p?=?next;
        ????}
        }
        int?query(int?x)
        {
        ????int?p?=?0;
        ????int?ans?=?0;
        ????for?(int?i?=?M;?i?>=?0;?--i)?{
        ????????int?idx?=?1?&?(x?>>?i);
        ????????if?(node[p][idx?^?1])?{
        ????????????ans?*=?2,?ans?+=?1;
        ????????????p?=?node[p][idx?^?1];
        ????????}
        ????????else?{
        ????????????ans?*=?2,?ans?+=?0;
        ????????????p?=?node[p][idx];
        ????????}
        ????}
        ????return?ans;
        }

        class?Solution?{
        public:
        ????unordered_map<?int,?vector<?pii?>?>?mp;
        ????vector<?int?>?son[N];
        ????void?dfs(int?u,?vector<?int?>?&ans)
        ????
        {
        ????????insert(u);
        ????????for?(auto?&i?:?mp[u])?ans[i.se]?=?query(i.fi);
        ????????for?(auto?&i?:?son[u])?dfs(i,?ans);
        ????????del(u);
        ????}
        ????vector<?int?>?maxGeneticDifference(vector<?int?>?&p,?vector<?vector<?int?>?>?&q)
        ????
        {
        ????????int?root?=?0;
        ????????for?(int?i?=?0;?i?<?p.size();?++i)?{
        ????????????if?(p[i]?!=?-1)
        ????????????????son[p[i]].push_back(i);
        ????????????else
        ????????????????root?=?i;
        ????????}
        ????????int?n?=?q.size();
        ????????for?(int?i?=?0;?i?<?n;?++i)?{
        ????????????q[i].pb(i);
        ????????????mp[q[i][0]].pb({?q[i][1],?q[i][2]?});
        ????????}
        ????????vector<?int?>?ans(n);
        ????????dfs(root,?ans);
        ????????return?ans;
        ????}
        };
        瀏覽 75
        點贊
        評論
        收藏
        分享

        手機掃一掃分享

        分享
        舉報
        評論
        圖片
        表情
        推薦
        點贊
        評論
        收藏
        分享

        手機掃一掃分享

        分享
        舉報
        1. <strong id="7actg"></strong>
        2. <table id="7actg"></table>

        3. <address id="7actg"></address>
          <address id="7actg"></address>
          1. <object id="7actg"><tt id="7actg"></tt></object>
            欧美国产一二三区 | 国产午夜激无码毛片不卡十第1集 | 超碰va| 黄色视频网站免费观看 | 五十多岁农村妇女形象 | 国产在线看片 | 黄片视频免费看的 | 97香蕉久久国产超碰青草软件 | 91蜜桃| 男人和美女的靠逼毛片 |