[leetcode 周赛 157] 1218 最长定差子序列

Posted slowbird

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了[leetcode 周赛 157] 1218 最长定差子序列相关的知识,希望对你有一定的参考价值。

1218 Longest Arithmetic Subsequence of Given Difference 最长定差子序列

问题描述

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

  • 示例 1:

输入:arr = [1,2,3,4], difference = 1
输出:4
解释:最长的等差子序列是 [1,2,3,4]。

  • 示例 2:

输入:arr = [1,3,5,7], difference = 1
输出:1
解释:最长的等差子序列是任意单个元素。

  • 示例 3:

输入:arr = [1,5,7,8,5,3,4,2,1], difference = -2
输出:4
解释:最长的等差子序列是 [7,5,3,1]。

  • 提示:
    • 1 <= arr.length <= 10^5
    • -10^4 <= arr[i], difference <= 10^4

思路

  • 读题
    顺序读取每个元素, 通过difference来筛选一个等差序列

动态规划

可以使用动态规划的思路, 建立两个函数:

  • F(k) 前k个元素中最长定差子序列的长度
  • G(num) 以元素num为定差子序列结尾的子序列长度

latex

当前元素num所在子序列长度等于前一个序列数num-difference所在子序列的长度+1
G[num] = G[num-difference]+1
如果num之前没有出现num-difference元素 则G[num-difference]为0

  • 实例
    arr = [1,5,7,8,5,3,4,2,1], difference = -2
步骤 已输入数 当前元素 最长定差子序列长度
1 1 G[1]=G[1-(-2)]+1=G[3]+1=0+1 =1 F[1]=1
2 1 5 G[5]=G[5-(-2)]+1=G[7]+1=0+1 =1 F[2]=1
3 1 5 7 G[7]=G[7-(-2)]+1=G[9]+1=0+1 =1 F[3]=1
4 1 5 7 8 G[8]=G[8-(-2)]+1=G[10]+1=0+1=1 F[4]=1
5 1 5 7 8 5 G[5]=G[5-(-2)]+1=G[7]+1=1+1 =2 F[5]=1
6 1 5 7 8 5 3 G[3]=G[3-(-2)]+1=G[5]+1=2+1 =3 F[6]=1
7 1 5 7 8 5 3 4 G[4]=G[4-(-2)]+1=G[6]+1=0+1 =1 F[7]=1
8 1 5 7 8 5 3 4 2 G[2]=G[2-(-2)]+1=G[4]+1=1+1 =2 F[8]=1
9 1 5 7 8 5 3 4 2 1 G[1]=G[1-(-2)]+1=G[3]+1=3+1 =4 F[9]=1
  • 图解
    动态规划

代码实现

动态规划

class Solution {
     public int longestSubsequence(int[] arr, int difference) {
         // res 输出结果 最长子序列长度
        int res = 0;
        // maps 存放键值出现时, 自己所在的定差子序列长度
        Map<Integer, Integer> maps = new HashMap<>(arr.length);

        // 相当于一个每次向右加+1的变长窗口
        for (int a : arr) {
            // 每个元素第一次出现时 初始值置为0
            if (!maps.containsKey(a)) {
                maps.put(a, 0);
            }
            // 该元素在子序列中前一个元素 可能出现的子序列长度(没有则为0)
            int pre = maps.get(a-difference) == null ? 0 : maps.get(a-difference);
            // 该元素子序列长度 比较自己所在序列以及前一个元素所在序列+1
            int na = Math.max(maps.get(a), pre+1);
            // 获取当前最大子序列长度
            res = Math.max(na, res);
            // 设置该元素所在子序列长度
            maps.put(a, na);
            //System.out.println(String.format("pre:%d na:%d res:%d maps:%s", pre, na, res, maps));
        }
        
        return res;
    }
}

参考资源

第 157 场周赛 全球排名
【算法实况】体验使用 iPadOS 打算法竞赛 - 力扣周赛 - LeetCode Weekly 157

以上是关于[leetcode 周赛 157] 1218 最长定差子序列的主要内容,如果未能解决你的问题,请参考以下文章

[leetcode 周赛 157] 1219 黄金矿工

leetcode每日一题-1218:最长定差子序列

leetcode:20210102周赛第四题——参加会议的最多员工数(基环树+找树枝+dfs最长树枝)

LeetCode 第 59 场力扣夜喵双周赛(最短路径数+迪杰斯特拉动态规划+最长公共前缀问题) / 第255场周赛(二进制转换,分组背包,子集还原数组(脑筋急转弯))

LeetCode 1218最长定差子序列[Map 动态规划] HERODING的LeetCode之路

leetcode打卡——等差数列题目(LIS变式)——1218. 最长定差子序列