【刷题日记】最长定差子序列

给你一个整数数组 arr 和一个整数 difference,请你找出并返回 arr 中最长等差子序列的长度,该子序列中相邻元素之间的差等于 difference 。

子序列 是指在不改变其余元素顺序的情况下,通过删除一些元素或不删除任何元素而从 arr 派生出来的序列。

这道题,看了一眼,劈里啪啦一分钟写完,自信写完,时间超限,天杀的我就知道我不可能一分钟做出mid题!!

/**
 * @param {number[]} arr
 * @param {number} difference
 * @return {number}
 */
var longestSubsequence = function(arr, difference) {
    const n=arr.length;
    const dp=new Array(n+1).fill(1);
    let res=0;
    for(var i=0;i<n;i++){
        for(var j=0;j<i;j++){
            if(arr[i]-arr[j]==difference){
                dp[i]=Math.max(dp[i],dp[j]+1);
            }
        }
        if(res<dp[i])res=dp[i];
    }
    return res;
};

没关系,我们来理思路,这至少说明前面几道题我能做到看见即秒了。

其实我们思路基本上是对的,但是得利用一点巧思。

 看官方给的思路。

因为我们每次都在左侧找一个最近的等于arr【i】-d元素并取其对应dp值。

因此我们直接用dp【v】表示以v为结尾的最长的等差子序列的长度 

官方题解使用了动态规划的方法来解决这个问题,并且为了优化空间复杂度,采用了哈希表(在 JavaScript 中是

官方题解使用了动态规划的方法来解决这个问题,并且为了优化空间复杂度,采用了哈希表(在 JavaScript 中是 Map 对象)来存储中间结果。这种方法的关键是理解状态转移方程和如何利用哈希表来高效地实现这个方程。

在这个问题中,状态转移方程是 `dp[v] = dp[v-d] + 1`,意味着如果存在一个值为 `v-d` 的元素,那么以值为 `v` 的元素结尾的最长等差子序列的长度可以从以 `v-d` 结尾的最长等差子序列的长度推导出来,即在后者基础上加一。

解题步骤

1. 初始化:创建一个 Map 对象 `dp` 来存储每个值作为等差子序列末尾时的最长长度。同时,初始化一个变量 `ans` 来记录遍历过程中找到的最长等差子序列的长度。

2. 遍历数组:遍历给定数组 `arr` 中的每个元素 `v`。

3. 更新 DP 表:对于当前元素 `v`,查找 `dp` 中 `v-difference`(即 `v-d`)的值。如果找到了,说明存在一个等差子序列以 `v-d` 结尾,那么以 `v` 结尾的最长等差子序列的长度就是以 `v-d` 结尾的最长等差子序列的长度加一。如果没有找到,说明以 `v` 为结尾的等差子序列只包含 `v` 本身,其长度为1(这里通过 `(dp.get(v - difference) || 0) + 1` 实现,如果 `dp.get(v - difference)` 返回 `undefined`,则用 `0` 替代)。

为了更好理解 也可以替换成

if(dp.get(v - difference) ==undefined){
    dp.set(v,1)
}else{
    dp.set(v,dp.get(v - difference)+1)
}

4. 更新最大长度:每次更新 `dp[v]` 后,用 `dp.get(v)` 更新 `ans`,确保 `ans` 始终是遍历到目前为止找到的最长等差子序列的长度。

5. 返回结果:遍历结束后,`ans` 存储的就是整个数组的最长等差子序列的长度。

var longestSubsequence = function(arr, difference) {
    let ans = 0;
    const dp = new Map();
    for (const v of arr) {
        dp.set(v, (dp.get(v - difference) || 0) + 1);
        ans = Math.max(ans, dp.get(v));
    }
    return ans;
};

这段代码实现了上述逻辑:

- 使用 `for (const v of arr)` 遍历数组。
- 对每个元素 `v`,通过 `dp.set(v, (dp.get(v - difference) || 0) + 1);` 更新哈希表,这里 `dp.get(v - difference) || 0` 是获取以 `v-difference` 结尾的最长等差子序列的长度,如果不存在则返回0,然后加1表示将当前元素 `v` 加入到等差子序列中。
- 使用 `ans = Math.max(ans, dp.get(v));` 更新找到的最长等差子序列的长度。
- 最终返回 `ans` 作为结果。

如果想把过程写的更加清晰一点就:

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值