算法-删除元素后最大固定点数目-典型最长增长序列算法

题目

给你一个整数数组 nums。

如果 nums[i] == i,则位置 i 被称为 固定点。

允许你从数组中删除 任意 数量的元素(包括零个)。在每次删除后,剩余元素 向左移动,并且下标从 0 开始重新分配。

返回一个整数,表示在执行任意次数的删除操作后,可以获得的 最大 固定点数量。

示例 1:

输入: nums = 0,2,1

输出: 2

解释:

  • 删除 nums[1] = 2。数组变为 [0, 1]。
  • 现在,nums[0] = 0 且 nums[1] = 1,因此两个下标都是固定点。
  • 因此,答案为 2。

题解

思路学习:本题跟俄罗斯套娃信封问题的解题思路一致,解决本题核心思考:

要求i==numsi,当i增加的时候numsi也需要增加,也就是连续增长序列,也即本题求最长连续增长序列

当数组中numsi的元素x需要移动i-x步时,比x大的元素numsj=z需要的移动步数必须大于i-x步时才能让i,j同时成为固定点位,因为numsi移动的i-x步的时候,numsj也会移动的i-x步,如果numsj需要的移动步数小于numsi时,则两者不能同时成为固定点位。需要维护numi开始的最长增长序列长度和numsj开始的最长增长序列长度。

java 复制代码
class Solution {
    public int maxFixedPoints(int[] nums) {
        List<int[]> a = new ArrayList<>();
        for (int i = 0; i < nums.length; i++) {
            int x = nums[i];
            if (i >= x) {
                a.add(new int[]{x, i - x});
            }
        }
        return maxEnvelopes(a);
    }

    // 354. 俄罗斯套娃信封问题
    private int maxEnvelopes(List<int[]> envelopes) {
        //对位置排序,小的元素在前,大的元素在后
        envelopes.sort((a, b) -> {
            if (a[0] == b[0]) {
                return b[1] - a[1];
            }
            return a[0] - b[0];
        });

        List<Integer> g = new ArrayList<>();
        for (int[] e : envelopes) {
            int h = e[1];
            //最长增长序列模版思路:用二分在数组找对应的位置,然后更新元素值
            // 允许 LIS 相邻元素相等
            int j = upperBound(g, h); 
            if (j < g.size()) {
                g.set(j, h);
            } else {
                g.add(h);
            }
        }
        return g.size();
    }

    private int upperBound(List<Integer> g, int target) {
        int left = -1, right = g.size(); // 开区间 (left, right)
        while (left + 1 < right) { // 区间不为空
            // 循环不变量:
            // nums[right] > target
            // nums[left] <= target
            int mid = left + (right - left) / 2;
            if (g.get(mid) > target) {
                right = mid; // 范围缩小到 (left, mid)
            } else {
                left = mid; // 范围缩小到 (mid, right)
            }
        }
        return right;
    }
}
相关推荐
erzong23124 分钟前
Linux操作系统:线程概念与控制
linux·算法
Nil2081 小时前
leetcode 5最长回文子串
算法·leetcode·职场和发展
xxwl5851 小时前
区域赛分类题解
c++·笔记·学习·算法
m0_674571971 小时前
力扣 hot 100 python
python·算法·leetcode
青少儿编程课堂2 小时前
蓝桥杯+全国青少年信息素养大赛+电子学会PythonC/C++考级:最长公共子序列LCS解析
c++·python·算法·bfs·信息学竞赛
倚楼听风语3 小时前
Kotlin 协程与 suspend 原理详解
java·算法·kotlin
程序员清风3 小时前
双指针与滑动窗口:高效处理连续区间
开发语言·算法
代钦塔拉3 小时前
【C++/Qt 进阶】设计模式系列(2):工厂模式——从游戏角色到披萨店
c++·算法·设计模式
思茂信息3 小时前
电磁仿真学涉及哪些算法?
人工智能·算法·数学建模·matlab·emc·电磁仿真·仿真辐射
糖果豆豆4 小时前
让 AI 自查三遍,它只会把错的说得更像对的——检查的人和被检查的,是同一个
算法·架构