Leetcode第334场周赛题解

文章目录

    • 简介
    • 第一题:2574. 左右元素和的差值
      • 思路:前缀和
      • 代码
    • 第二题:2575. 找出字符串的可整除数组
      • 思路:余数
      • 代码
    • 第三题:2576. 求出最多标记下标
      • 思路:双指针
      • 代码
    • 第四题:2577. 在网格图中访问一个格子的最少时间
      • 思路:Dijkstra
      • 代码

简介

Leetcode第334场周赛,一共4道题,时间1.5h

第一题:2574. 左右元素和的差值

2574. 左右元素和的差值

思路:前缀和

  • 前缀和:即统计每一个位置i的sum(nums[0],nums[1],,,,nums[i-1])
  • 这一题具体统计的是i的前缀、后缀和,即求abs(leftSum[i]-rightSum[i])

代码

vector<int> leftRigthDifference(vector<int> &nums)
{
    int *left = new int[nums.size()];
    int *right = new int[nums.size()];
    memset(left, 0, sizeof(left));
    memset(right, 0, sizeof(right));
    vector<int> ans;
    for (int i = 0; i < nums.size(); i++)
    {
        if (i == 0)
        {
            left[i] = 0;
        }
        else
        {
            left[i] = left[i - 1] + nums[i - 1];
        }
    }
    for (int i = nums.size() - 1; i >= 0; i--)
    {
        if (i == nums.size() - 1)
        {
            right[i] = 0;
        }
        else
        {
            right[i] = right[i + 1] + nums[i + 1];
        }
    }
    for (int i = 0; i < nums.size(); i++)
    {
        ans.push_back(abs(left[i] - right[i]));
    }
    return ans;
}

第二题:2575. 找出字符串的可整除数组

2575. 找出字符串的可整除数组

思路:余数

  • 主要考量的是数学中余数相关的知识
  • 当前位置i代表数字word[i]-'0',即为tp;
  • i=0,且tp % m == 0i位置是一个可整除的位置,否则记录余数tpmod = tp % m;
  • i > 0,则若(tp + tpmod * 10)%m==0,则i位置是一个可整除的位置,否则更新余数tpmod = (tp + tpmod * 10) % m

代码


vector<int> divisibilityArray(string word, int m)
{
    vector<int> ans(word.size(), 0);
    long long tp = 0;
    long long tpmod = 0;
    int lastInd = -1;
    for (int i = 0; i < word.size(); i++)
    {
        tp = word[i] - '0';
        long long check = (tp + tpmod * 10) % m;
        tpmod = check;
        if (tpmod == 0)
        {
            ans[i] = 1;
            lastInd = i;
        }
    }

    return ans;
}

第三题:2576. 求出最多标记下标

2576. 求出最多标记下标

思路:双指针

  • 排序 + 双指针
  • 先将nums从小到大排序O(nlogn)
  • 设置双指针left、right,初始化left = 0,从nums的后半段中找到第一个 >= 2*nums[left]的位置,赋值给right
  • Tip: 之所以在后半段找,因为ans最大不会超过nums.size()
  • 向右分别移动left、right并统计即可

代码


int maxNumOfMarkedIndices(vector<int> &nums)
{
    sort(nums.begin(), nums.end());
    int n = nums.size();
    int ans = 0;
    int i;
    for (i = n / 2; i < n; i++)
    {
        if (nums[i] >= 2 * nums[0])
            break;
    }
    int left = 0, right = i;
    while (right < n && left < i)
    {
        if (nums[right] >= 2 * nums[left])
        {
            ans++;
            left++;
        }
        right++;
    }
    return ans * 2;
}

第四题:2577. 在网格图中访问一个格子的最少时间

2577. 在网格图中访问一个格子的最少时间

思路:Dijkstra

参考:灵茶山艾府的思路

  • dijkstra,设dist[i][j]表示到达该位置最短用时
  • 核心在与发现:
  • dist[i][j]和i+j同奇偶,若否则dist[i][j]+=1
  • dist[i][j] >= grid[i][j]
  • 满足上面的限制就可以开始 dijkstra

代码

int moves[5] = {-1, 0, 1, 0, -1};

int minimumTime(vector<vector<int>> &grid)
{
    int m = grid.size();
    int n = grid[0].size();
    // 无法到达
    if (grid[0][1] > 1 || grid[1][0] > 1)
        return -1;
    // 距离方式
    int dist[m][n];
    // 初始化无限大
    memset(dis, 0x3f, sizeof(dis));
    dist[0][0] = 0;
    priority_queue<tuple<int, int, int>, vector<tuple<int, int, int>>, greater<>> nodes;
    nodes.emplace(0, 0, 0);
    while (1)
    {
        auto [d, i, j] = nodes.top();
        nodes.pop();
        if (i == m - 1 && j == n - 1)
            return d;
        else
        {
            int nd;
            for (int k = 0; k <= 3; k++)
            {
                if (i + moves[k] < 0 || i + moves[k] >= grid.size() || j + moves[k + 1] >= grid[0].size() || j + moves[k + 1] < 0)
                    continue;
                nd = max(d + 1, grid[i + moves[k]][j + moves[k + 1]]);
                nd += (nd - (i + moves[k]) - (j + moves[k + 1])) % 2;
                if (nd < dist[i + moves[k]][j + moves[k + 1]])
                {
                    dist[i + moves[k]][j + moves[k + 1]] = nd;
                    nodes.emplace(nd, i + moves[k], j + moves[k + 1]);
                }
            }
        }
    }
}

你可能感兴趣的:(算法题解,leetcode,算法,数据结构)