天天看點

LeetCode第321場周賽題解

這周周賽沒有什麼過多難的 也是可以自己寫完的 (蕪湖)

第一道題

 6245. 找出中樞整數

給你一個正整數 n ,找出滿足下述條件的 中樞整數 x :

1 和 x 之間的所有元素之和等于 x 和 n 之間所有元素之和。

傳回中樞整數 x 。如果不存在中樞整數,則傳回 -1 。題目保證對于給定的輸入,至多存在一個中樞整數。

示例 1:

輸入:n = 8

輸出:6

解釋:6 是中樞整數,因為 1 + 2 + 3 + 4 + 5 + 6 = 6 + 7 + 8 = 21 。

思路: 這道題 一看就要用到字首和 的知識 這道題在比賽的時候我用的是 字首和數組 和 字尾和數組一起加逼 得到答案其實并不需要

比賽時候的代碼:

class Solution {
public:
    int pivotInteger(int n) {
        vector<int> presum(n);
        vector<int> postsum(n);
        for(int i=0;i<n;++i)
        {
            presum[i]=i+1;
            postsum[i]=i+1;
        }
        for(int i=1;i<n;++i)
        {
            presum[i]+=presum[i-1];
            postsum[n-1-i]+=postsum[n-1-i+1];
        }
        for(int i=0;i<n;++i)
        {
            if(presum[i]==postsum[i]) return i+1;
        }
        return -1;
    }
};
           

多了一個字尾和的代碼 其實沒必要 統計一下sum是多少就好了 然後再減一下就ok

代碼如下:

class Solution {
public:
    int pivotInteger(int n) {
        vector<int> presum(n+1);
        int sum=0;
        for(int i=0;i<=n;++i)
        {
            presum[i]=i+1;
            if(i) presum[i]+=presum[i-1];
            sum+=i;
        }
        for(int i=1;i<=n;++i)
        {
            if(presum[i]==sum-presum[i-1]) return i+1;
        }
        return -1;
    }
};
           

第二題

6246. 追加字元以獲得子序列

給你兩個僅由小寫英文字母組成的字元串 s 和 t 。

現在需要通過向 s 末尾追加字元的方式使 t 變成 s 的一個 子序列 ,傳回需要追加的最少字元數。

子序列是一個可以由其他字元串删除部分(或不删除)字元但不改變剩下字元順序得到的字元串。輸入:s = "coaching", t = "coding"

輸出:4

解釋:向 s 末尾追加字元串 "ding" ,s = "coachingding" 。

現在,t 是 s ("coachingding") 的一個子序列。

可以證明向 s 末尾追加任何 3 個字元都無法使 t 成為 s 的一個子序列。

思路:

這道題也并不難 一開始了解錯了 以為是找子串問題 然後就用了 kmp 送出之後看了 錯誤示例 我就知道哪裡錯了 然後 就發現 想複雜了 

好了 閑話不多說 講思路了 這道題的意思就是 尋找在s 中的 t的 子串 含義 s中含有的t的字元串可以不連貫 但必須是 t的 順序 意思就是 s=ktr   t = kr t就是 s的子序列 但是 如果 s=ing t=ni 那s需要補充一個i 才能實作 是以很好實作這道題 

代碼如下:

class Solution {
public:
    int appendCharacters(string s, string t) {
        int i=0,j=0;
        while(i<s.size())
        {
            if(j==t.size()) return 0;
            if(s[i]==t[j]) j++;
            i++;
        }
        return t.size()-j;
    }
};
           

第三題

6247. 從連結清單中移除節點

給你一個連結清單的頭節點 head 。

對于清單中的每個節點 node ,如果其右側存在一個具有 嚴格更大 值的節點,則移除 node 。

傳回修改後連結清單的頭節點 head 。

思路 : 利用單調棧 可以維護一個單調小棧 通過維護這個單調小棧 就可以知道 哪些點需要留 哪些點 需要扔掉

deque<int> mp;
        while(h)
        {
            while(!mp.empty() && h->val > mp.back()) mp.pop_back();
            mp.push_back(h->val);
            h=h->next;
        }
           

 再從連結清單頭開始周遊連結清單 如果他是單調棧中的元素 就保留 不是就删除 

if(s->val!=mp.front())
             {
                s->next==NULL;
                delete s;
            }
           

如果他是單調棧的元素 就需要判斷他是不是頭節點 我們可以引入一個pre變量 初始化為NULL 可以通過這個來重新将連結清單串起來

//第一個點
                if(pre==NULL) {
                    head=s;
                    pre=s;
                }
                //後續節點
                else {
                    pre->next=s;
                    pre=s;
                }
           

完整代碼如下:

class Solution {
public:
    ListNode* removeNodes(ListNode* head) {
        ListNode* h=head;
        deque<int> mp;
        while(h)
        {
            while(!mp.empty() && h->val > mp.back()) mp.pop_back();
            mp.push_back(h->val);
            h=h->next;
        }
        ListNode* pre=NULL;
        ListNode* temp=head;
        while(temp)
        {
            ListNode* s=temp;
            temp=temp->next;
            if(s->val!=mp.front()) {
                s->next==NULL;
                delete s;
            }
            else {
                mp.pop_front();
                //第一個點
                if(pre==NULL) {
                    head=s;
                    pre=s;
                }
                //後續節點
                else {
                    pre->next=s;
                    pre=s;
                }
            }
        }
        return head;
    }
};
           

第四題

6248. 統計中位數為 K 的子數組

給你一個長度為 n 的數組 nums ,該數組由從 1 到 n 的 不同 整數組成。另給你一個正整數 k 。

統計并傳回 num 中的 中位數 等于 k 的非空子數組的數目。

注意:

數組的中位數是按 遞增 順序排列後位于 中間 的那個元素,如果數組長度為偶數,則中位數是位于中間靠 左 的那個元素。

例如,[2,3,1,4] 的中位數是 2 ,[8,4,3,5,1] 的中位數是 4 。

子數組是數組中的一個連續部分。

示例 1:

輸入:nums = [3,2,1,4,5], k = 4

輸出:3

解釋:中位數等于 4 的子數組有:[4]、[4,5] 和 [1,4,5] 。

思路: 這道題 利用的前字尾和 來解題 

#1找到k的位置 同時将 nums數組分别分為 大于 k的(1) 等于k的 (0) 和 小于k的(-1) 友善來計數

// 找出k所在下标idx
        for(int i=0;i<n;i++)
        {
            if(nums[i]==k)
            {
                index = i;
            }
            if(nums[i]<k)
            nums[i] = -1;
            else if(nums[i]==k)
            nums[i] = 0;
            else
            nums[i] = 1;
        }
           

#2 先周遊 idx之後的數 看有幾個大于k的 有幾個小于k的 利用一張hash_map來計數 分别記錄 從idx開始 有幾種情況 

// 枚舉idx之後的數與idx+idx之前字尾和的和,和為0或1的數目可計入答案
        unordered_map<int,int> m;
        int s = 0;
        for(int i=index+1;i<n;i++)
        {
            s += nums[i];
            m[s] += 1;
        }
           

題目說偶數是記錄上中位數的 是以我們可以看2個點 0或者1 的點 這兩個點都符合題意 

// 枚舉idx與idx之前字尾和的和,和為0或1的數目可計入答案
        for(int i=index;i>=0;i--)
        {
            s += nums[i];
            if(m.find(-s)!=m.end())
            {
                res += m[-s];
            }
            

            if(m.find(1-s)!=m.end())
            {
                res += m[1-s];
            }
            
        }
           

完整代碼如下:

class Solution {
public:
    int countSubarrays(vector<int>& nums, int k) {
        int index = 0;
        int res = 0;
        int n = nums.size();
        // 找出k所在下标idx
        for(int i=0;i<n;i++)
        {
            if(nums[i]==k)
            {
                index = i;
            }
            if(nums[i]<k)
            nums[i] = -1;
            else if(nums[i]==k)
            nums[i] = 0;
            else
            nums[i] = 1;
        }

        // 枚舉idx之後的數與idx+idx之前字尾和的和,和為0或1的數目可計入答案
        unordered_map<int,int> m;
        int s = 0;
        for(int i=index+1;i<n;i++)
        {
            s += nums[i];
            m[s] += 1;
        }

        m[0] += 1;
        s = 0;

        // 枚舉idx與idx之前字尾和的和,和為0或1的數目可計入答案
        for(int i=index;i>=0;i--)
        {
            s += nums[i];
            if(m.find(-s)!=m.end())
            {
                res += m[-s];
            }
            

            if(m.find(1-s)!=m.end())
            {
                res += m[1-s];
            }
            
        }
        return res;
    }
};