Leetcode周赛370总结

Q1 找到冠军 I

  • 题目链接

  • 解题思路:

    • 遍历矩阵每行
    • 如果只存在一行满足行内有n-1个1,返回该行的行号
    • 否则返回-1
  • 解题代码:


class Solution {
public:
    int findChampion(vector<vector<int>>& grid) {
        int n = grid.size();
        for(int i = 0; i < n; i++)
        {
            int cnt = count(grid[i].begin(), grid[i].end(), 1);
            if(cnt == n-1)
                return i;
        }
        return -1;
    }
};


  • 当然也可以从列的角度来考虑,如果j列全部为0,则表示没有任何选手可以击败j
  • 解题代码:
class Solution {
public:
    int findChampion(vector<vector<int>>& grid) {
        int n = grid.size();
        for(int j = 0; j < n; j++)
        {
            bool state = true;
            for(int i = 0; i < n; i++)
            {
                if(grid[i][j] == 1)
                {
                    state = false;
                    break;
                }
            }
            if(state)
                return j;
        }
        return -1;
    }
};

Q2 找到冠军 II

  • 题目链接

  • 解题思路:

    • 统计入度为0的点
    • 如果恰好只有一个点,返回该点
    • 否则返回-1
  • 解题代码:

class Solution {
public:
    int findChampion(int n, vector<vector<int>>& edges) {
        vector<int> deg(n, 0);
        for(auto &edge : edges)
        {
            int x = edge[0];
            int y = edge[1];
            deg[y] += 1;
        }

        int ans = -1;
        for(int i = 0; i < n; i++)
        {
            if(deg[i] == 0)
            {
                if(ans == -1)
                    ans = i;
                else
                    return -1;
            }
        }

        return ans;
    }
};

Q3 在树上执行操作以后得到的最大分数

  • 题目链接

  • 解题思路:

    • 定义dfs(x, fa),表示从x节点(选取/未选取)开始遍历到根节点可以得到的最大分数

    • 状态转移:

      • 如果不选x,则可以选x的所有子树中的所有元素
      • 如果选了x,则x的每一颗子树上都得有一个不选的元素,dfs(x, fa, state) = sum(dfs(y, x)),其中y是x的子节点
    • 当到了叶子节点,必须不选了,返回0

    • 递归入口:dfs(0, -1)

    • 可以不用记忆化搜索的

  • 解题代码:


class Solution {
public:
    long long maximumScoreAfterOperations(vector<vector<int>>& edges, vector<int>& values) {
       
        int n = values.size();
        vector<vector<int>> g(n);
        for(auto edge : edges)
        {
            int x = edge[0];
            int y = edge[1];
            g[x].push_back(y);
            g[y].push_back(x);
        }  
        vector<long long> sum(n, 0);
        function<long long(int, int)> dfs = [&](int x, int fa) -> long long
        {
            long long ans = values[x];
            for(auto y : g[x])
            {  
                if(y != fa)
                    ans += dfs(y, x);
            }
            sum[x] = ans;
            return ans;
        };
        dfs(0, -1);
        vector<long long> f(n, -1);
        function<long long(int, int)> dfs2 = [&](int x, int fa) -> long long
        {
            if(g[x].size() == 1 && g[x][0] == fa)
                return 0;
           
            if(f[x] != -1)
                return f[x];
            long long ans1 = sum[x] - values[x];
            long long ans2 = values[x];
            for(auto y : g[x])
            {  
                if(y != fa)
                    ans2 += dfs2(y, x);
            }
            f[x] = max(ans1, ans2);
            return f[x];
        };
        return dfs2(0, -1);
    }
};


Q4 平衡子序列的最大和

  • 题目链接
  • 解题思路:
    • 数据结构优化 DP

    • 定义b[i] = nums[i] - i,问题变成从b中选出一个非降子序列,求对应的nums的元素和的最大值

    • 定义f[i]表示子序列最后一个数的下标是i时,对应的nums的元素和的最大值,答案会是max(f)

    • f[i] = max(max(f[j], 0)) + nums[i],j满足 j < i 且 b[j] <= b[i]

    • 使用权值树状数组优化,树状数组维护前缀最大值

      • 设下标x = b[i],维护的值为max(f[x],f[x-1],f[x-2],…)
    • 实现时需要将nums[i] - i 离散化,在使用树状数组 复制 + 排序 + 去重

    • 树状数组 区间最大值 + 单点更新

  • 解题代码:

class BIT{
    public:
        BIT(){}
        BIT(int n):tree(n, LONG_LONG_MIN){}
        void update(int i, long long val)
        {
            while(i < tree.size())
            {
                tree[i] = max(tree[i], val);
                i += i & -i;
            }
        }
        long long preMax(int i)
        {
            long long res = LONG_LONG_MIN;
            while(i > 0)
            {
                res = max(res, tree[i]);
                i &= i-1;
            }
            return res;
        }
    private:
        vector<long long> tree;
};
class Solution {
public:
    long long maxBalancedSubsequenceSum(vector<int>& nums) {
        int n = nums.size();
        vector<int> b(n);
        for(int i = 0; i < n; i++)
            b[i] = nums[i] - i;
       
        sort(b.begin(), b.end());
        b.erase(unique(b.begin(), b.end()), b.end()); //去重
        BIT t = BIT(b.size() + 1);
        for(int i = 0; i < n; i++)
        {
            int j = lower_bound(b.begin(), b.end(), nums[i] - i) - b.begin() + 1;
            long long temp = max(t.preMax(j), 0ll) + nums[i];
            t.update(j, temp);
        }
        return t.preMax(b.size());
    }
};

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值