佳期投资专场——第321场LeetCode周赛题解

目录

前缀数组:6245. 找出中枢整数

双指针:6246. 追加字符以获得子序列

数组模拟:6247. 从链表中移除节点

中心扩散:6248. 统计中位数为 K 的子数组


前缀数组:6245. 找出中枢整数

这题不清楚暴力是否能过,要是每一次都计算一遍和肯定很浪费计算资源。

我们可以把前缀和计算一遍,再把后缀和计算一遍,这个复杂度是O(N+N)

然后再把遍历一遍,返回前缀数组和后缀数组相等的即可。

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

双指针:6246. 追加字符以获得子序列

这题乍一看是KMP,但是KMP是要把模板数组全部匹配,这题不用这么麻烦。直接双指针遍历,让指向字符串s的指针走的快,指向字符串t的指针走得慢,tp就是两个字符串相互重复的最大部分。

class Solution {
public:
    int appendCharacters(string s, string t) {
        int ts = 0;
        int tp = 0;
        while (ts <= s.size() && tp <= s.size()) {
            if (s[ts] == t[tp]) {
                ts ++;
                tp ++;
            } else {
                ts ++;
            }
        }
        if (t.size() - tp == -1) {
            return 0;
        }
        return t.size() - tp;
    }
};

数组模拟:6247. 从链表中移除节点

这题的关键在于我们需要从右向左看,但是单向链表逆序遍历又比较麻烦,所以我们先遍历一遍链表,将所有链表的值保存下来。

然后从右往左遍历数组,只保留下右侧没有比其更大的节点。

最后再新建一个链表,当然你也可以在原来的链表上删除,因为第二步得出了需要保存节点的val。

/**
 * Definition for singly-linked list.
 * struct ListNode {
 *     int val;
 *     ListNode *next;
 *     ListNode() : val(0), next(nullptr) {}
 *     ListNode(int x) : val(x), next(nullptr) {}
 *     ListNode(int x, ListNode *next) : val(x), next(next) {}
 * };
 */
class Solution {
public:
    ListNode* removeNodes(ListNode* head) {
        if (head->next == nullptr) {
            return head;
        }
        vector<int> v;
        while (head) {
            v.push_back(head->val);
            head = head->next;
        }
        int backmax[v.size()];
        int maxnum = v[v.size() - 1];
        backmax[v.size() - 1] = maxnum;
        for (int i = v.size() - 2; i >= 0; i--) {
            if (v[i] < maxnum) {
                backmax[i] = maxnum;
            } else {
                backmax[i] = v[i];
                maxnum = v[i];
            }
        }
        vector<int> last;
        for (int i = 0; i < v.size(); i++) {
            if (v[i] >= backmax[i]) {
                last.push_back(v[i]);
            }
        }
        ListNode* dummy = new ListNode(-1);
        ListNode* cur = dummy;
        for (int i = 0; i < last.size(); i++) {
            ListNode* temp = new ListNode(last[i]);
            cur->next = temp;
            cur = cur->next;
        }
        return dummy->next;
    }
};

中心扩散:6248. 统计中位数为 K 的子数组

这题我没来得及写完,我当时的思路很简单:回溯得到所有子数组,然后遍历一遍得到符合条件的数量。

但是连续子数组用回溯不好写,如果用暴力双循环的话,复杂度O(N*N),这样也过不了。

后来看到到来用中心扩散过了,笑死:力扣

class Solution {
public:
    int countSubarrays(vector<int>& nums, int k) {
        int n=nums.size(),idx=-1;
        for(int i=0;i<n;i++)
        {
            if(nums[i]==k)idx=i;
        }
        if(idx==-1)return 0;
        int cnt=0,sum=0;
        unordered_map<int,int>left;
        left[0]=1;
        
        for(int i=idx-1;i>=0;i--)
        {
            if(nums[i]<k)sum--;
            else sum++;
            left[sum]++;
        }
        cnt+=left[0];
        cnt+=left[1];
        sum=0;
        for(int i=idx+1;i<n;i++)
        {
            if(nums[i]<k)sum--;
            else sum++;
            cnt+=left[-1*sum];
            cnt+=left[1-sum];
        }
        return cnt;
    }
};

再加油吧!

猜你喜欢

转载自blog.csdn.net/qq_41895747/article/details/128064154
今日推荐