小米前端笔试题记录——动态规划

选择题

Promise.all, race,allSettled

下面关于Promise说法正确的是(注意“返回结果”的意思包含成功或者失败):

A. Promise.all在所有给定的promise都fulfilled后才返回结果
B. Promise.race在给定的promise中,某个fulfilled后才返回结果
C. promise.then的回调函数中,可以返回一个新的promise
D. 对于一个向后台获取数据已经产生结果的promise:p1,再次调用p1.then,不会去重新发起请求获取数据

答案:CD

Promise.all 是指,将多个promise包装成数组,一起触发,若全部fulfilled则成功,若有一个rejected则失败,整体抛出的异常为第一个失败的promise抛出的异常。最终只返回一个Promise,若全部成功,则返回的value为一个数组,包装时内部的顺序与完成后的顺序一致。

在这里插入图片描述

在这里插入图片描述

Promise.race 是指,将多个promise包装成数组,一起触发,只要有一个且是第一个成功或失败则整体的结果就是这个promise的结果。该方法只返回一个Promise

在这里插入图片描述

Promise.allSettled 是指,将多个promise包装成数组,一起触发,当全部子内容完成后返回一个Promise,其中有results表示结果。

在这里插入图片描述

Vue、React 双向数据流

注意双向数据流和双向绑定的区别,vue和react都是双向数据流,只不过一个是单向绑定,一个是双向绑定。

HTTPS

在这里插入图片描述

会改变原数组的数组方法 push splice

concat slice 等会返回一个新数组
map 会使用返回值的方法返回一个新数组

在这里插入图片描述

outline-width 不会触发回流

因为outline-width轮廓线不会占据空间

附加题:动态规划

在这里插入图片描述

前言

其实这个题是比较难直接想到一维动态规划的,因为,牵扯到要证明满足一个前缀和原理的问题。

就是为什么i到j的步数,等于1到 j 的步数 减去1到 i 的步数,即 step{i, j} = step{1, j} - step{1, i} 很多人在这里直接直接用了这个规则,但是我在做题的时候是没有想通这一点的,因此我在看到别人的题解之后还是比较震惊的,居然满足前缀和公式。

因为我的理解是,当你从1到 i 或从1到 j 时,必定满足,前面已走过的节点必定是偶数倍,但是从 ij 则不然,i 之前的节点不一定是要偶数的,这两个问题的状态是不一样的。

我的思路

接下来说说我的思路,我使用的是记忆化搜索。我觉得这个是比较容易直接想到的方法。一维想不出来就用二维,dp[i][j] 表示,从i到j所需的步数。我们最终求解的目的是 dp[1][n+1]

我们设在一个计算单元内的思路是这样的:

目标 x -> y     必定会经过下面的步骤
x -> y-1        这是第一次达到 y-1,消耗a1步
y-1 -> c[y-1]   经过规则1返回上一个规定的位置,消耗1步
c[y-1] -> y-1   第二次达到y-1,消耗a2步
y-1 -> y        最终达到y,消耗1步
                总消耗a1+a2+2步

因此这个计算单元其实很好写

int getStep(int start, int end) {
    if (dp[start][end] != -1) return dp[start][end];
    int a1 = getStep(start, end - 1);
    a1 += 1;
    int a2= getStep(c[end-1], end-1);
    a2 += 1;
    return (a1 + a2) % M;
}

但是学过动态规划就知道,这样会造成大量的重复计算,因此需要改造:

int getStep(int start, int end) {
    if (dp[start][end] != -1) return dp[start][end];
    int a1 = getStep(start, end - 1);
    int a2= getStep(c[end-1], end-1);
    dp[start][end] = a1 + a2 + 2;
    return dp[start][end]%M;
}

对于一次 dp[i][j] 的计算,我们要把结果保留下来,再下次计算的时候,如果这个位置被计算过,则直接返回结果。

总时间复杂度与一维dp无异。

总代码:

#include
#include
#include
#include
using namespace std;

int getStep(int start, int end);

int dp[N][N];
int c[N];
const int N = 1005;
const int M = 1000000007;

int main () {
    int n;
    cin>>n;
    for (int i=0;i>c[i+1];
    for (int i=1;i<=n;++i)
        for (int j=1;j<=n+1;++j)
            dp[i][j] = -1;
    for (int i=1;i<=n+1;++i) dp[i][i] = 0;
    printf("%d", getStep(1, n+1));
    return 0;
}

int getStep(int start, int end) {
    if (dp[start][end] != -1) return dp[start][end];
    int a1 = getStep(start, end - 1);
    int a2= getStep(c[end-1], end-1);
    dp[start][end] = a1 + a2 + 2;
    return dp[start][end]%M;
}
  • 2
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 8
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 8
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值