Leetcode每日一题 —— 3534. 针对图的路径存在性查询 II

魔法师 2026-07-10 10:05 1



思路


参考昨天的题目,今天题目第一件事肯定是排序,并记录定位。

一开始我是用快慢指针来确定每个节点(排序后)能到达的最大节点,但是在遍历queries的时候TLE了。


那么现在的问题就是如何加速了。首先想到的是把src能达到的所有步数的长度都存起来(借助指针可以只存一遍让时间复杂度降低),然后二分去查找,但是这样还挺麻烦的,反过来想,我们可以逆向二分也就是借助st表的概念,直接存幂次的步数。这样时间复杂度应该就没问题了。




TLE代码

class Solution {
public int[] pathExistenceQueries(int n, int[] nums, int maxDiff, int[][] queries) {
Integer[] idx = new Integer[n];
for (int i = 0; i < n; i++) {
idx[i] = i;
}
Arrays.sort(idx, Comparator.comparingInt(i -> nums[i]));
int[] pos = new int[n];
for (int i = 0; i < n; i++) {
pos[idx[i]] = i;
}

int[] right = new int[n];
int fast = 0;
for (int slow = 0; slow < n; slow++) {
while (fast < n && nums[idx[fast]] - nums[idx[slow]] <= maxDiff) {
fast++;
}
right[slow] = fast - 1;
}

int[] ans = new int[queries.length];
for (int i = 0; i < queries.length; i++) {
int src = pos[queries[i][0]];
int dist = pos[queries[i][1]];
if (src > dist) {
int t = src;
src = dist;
dist = t;
}
if (src == dist) {
continue;
}
int step = 1;
while (right[src] < dist) {
if (right[src] == src) {
step = -1;
break;
}
src = right[src];
step++;
}
ans[i] = step;
}
return ans;
}
}


代码


class Solution {
public int[] pathExistenceQueries(int n, int[] nums, int maxDiff, int[][] queries) {
Integer[] idx = new Integer[n];
for (int i = 0; i < n; i++) {
idx[i] = i;
}
Arrays.sort(idx, Comparator.comparingInt(i -> nums[i]));
int[] pos = new int[n];
for (int i = 0; i < n; i++) {
pos[idx[i]] = i;
}

int maxPow = 32 - Integer.numberOfLeadingZeros(n);
int[][] right = new int[n][maxPow];
int fast = 0;
for (int slow = 0; slow < n; slow++) {
while (fast < n && nums[idx[fast]] - nums[idx[slow]] <= maxDiff) {
fast++;
}
right[slow][0] = fast - 1;
}
for (int j = 1; j < maxPow; j++) {
for (int i = 0; i < n; i++) {
right[i][j] = right[right[i][j - 1]][j - 1];
}
}

int[] ans = new int[queries.length];
for (int i = 0; i < queries.length; i++) {
int src = pos[queries[i][0]];
int dist = pos[queries[i][1]];
if (src > dist) {
int t = src;
src = dist;
dist = t;
}
if (src == dist) {
continue;
}
int step = 0;
for (int j = maxPow - 1; j >= 0; j--) {
if (right[src][j] < dist) {
src = right[src][j];
step |= 1 << j;
}
}
ans[i] = right[src][0] < dist ? -1 : step + 1;
}
return ans;
}
}
最新回复 (1)
  • SomeBottle 07-10 12:20
    1

    今天没时间和困难题耗了,选了道中等题做:


    1035. 不相交的线 - 力扣(LeetCode)


    定睛一看,这不最长公共子序列吗…


    class Solution {
    public:
    int maxUncrossedLines(vector<int>& nums1, vector<int>& nums2) {
    // 两个数组长度不一定相等
    // 仔细一看,这不求最长公共子序列吗
    int n1=nums1.size();
    int n2=nums2.size();
    // n+1,保留一个数字都不选的情况
    vector<vector<int>> dp(n1+1,vector<int>(n2+1,0));
    // 开始递推
    for(int i=1;i<=n1;i++){
    for(int j=1;j<=n2;j++){
    if(nums1[i-1]==nums2[j-1]){
    // 此处两个字符相等
    dp[i][j]=dp[i-1][j-1]+1;
    }else{
    dp[i][j]=max(dp[i-1][j],max(dp[i][j-1],dp[i-1][j-1]));
    }
    }
    }
    return dp[n1][n2];
    }
    };
* 帖子来源Linux.do
返回