力扣周赛250期(下)

267 阅读1分钟

这是我参与8月更文挑战的第10天,活动详情查看:8月更文挑战

1936. 新增的最少台阶数

截屏2021-08-10 下午9.58.13.png

思路分析

看起来是简单的一次遍历但是会在数据量过大的时候,出现问题。

在遇到两个相邻数组元素之间需要插入多个台阶的时候,如果使用如下方式

for(int i = 0; i < rungs.size(); i++){ 
    if(rungs[i] - tmp > dist){ 
        tmp += dist; ret++; i--; 
    }else{ 
        tmp = rungs[i]; 
    } 
}

那么时间复杂度其实就是O(Max(rungs)/dist),当然按照时间复杂度的写法应该是O(Max(rungs)/dist)

在发现超时后我们设法剪枝,使用如下方式将时间复杂度降低

tmp = rungs[i] - rungs[i - 1];
if (tmp > dist){
    ret += tmp/dist - 1;
    if(tmp % dist != 0)ret++;
}

1937 扣分后的最大得分

截屏2021-08-10 下午11.12.28.png

思路分析

这道题也是具有很明显的子问题用来求解总问题的特征。我们很容易写出代码

//假装有初始化代码
 for(int i = 1; i < m; i++){
    for(int j = 0; j < n; j++){
        int maxt = -1;
        for(int k = 0; k < n; k++){
            maxt = max(arr[i - 1][k] - abs(j - k),maxt);
        }
        arr[i][j] = maxt + points[i][j];
    }
}
int maxt = -1;
for(int i = 0; i < n; i++){
    maxt = max(maxt, arr[m - 1][i]);
}

但很明显时间复杂度到达了O(mn2)O(mn^2),假设m==n,则时间复杂度为O(n3)O(n^3),这就导致了超时。那么如何优化呢?

我们可以将

f[i][j]=max{f[i1][j]jj}+points[i][j]f[i][j]=max\{f[i−1][j^′]−∣j−j^′∣\}+points[i][j]

转化为

f[i][j]=max{f[i1][j]j}+points[i][j]+jf[i][j] = max\{f[i−1][j^′]−j^′\}+ points[i][j]+j

,很明显,只有在j'小于j的时候,该公式成立,因此,再反向计算一次,比较两次得到的最大值作为答案。

由于公式中表达式右边不存在f[i][k],因此两次计算可以同时计算,互不发生冲突。