队列(中等) | 豆包MarsCode AI刷题

35 阅读2分钟

问题描述

给定一个长度为 nn 的序列 a1,a2,,ana_1, a_2, \dots, a_n,你可以选择删去其中最多 n1n-1 个数,得到一个新序列 b1,b2,,bmb_1, b_2, \dots, b_m1mn1 \le m \le n),新序列保留原来的相对顺序。你的目标是删除某些数,使得新序列的第 ii 个数 bi=ib_i = i。现在需要求出最少删除多少个数才能得到这样的序列,如果无法得到,输出 1-1。 例如,对于序列 [1, 4, 2, 3, 5],删除第 2 个和第 5 个元素后,可以得到序列 [1, 2, 3]

样例

样例一:

输入:n = 5 ,a = [1, 4, 2, 3, 5]
输出:2

样例二:

输入:n = 3 ,a = [3, 3, 2]
输出:-1

样例三:

输入:n = 5 ,a = [1, 2, 3, 4, 5]
输出:0

解题思路

  1. 理解问题

    • 我们需要找到一个子序列,使得这个子序列中的每个元素都等于其在子序列中的位置(从1开始)。
    • 例如,对于序列 [1, 4, 2, 3, 5],删除第 2 个和第 5 个元素后,可以得到序列 [1, 2, 3],这个序列满足条件。
    • 通俗点说,这个序列就是要从1开始逐个递增。
  2. 数据结构选择

    • 由于我们需要保留元素的相对顺序,并且需要频繁地检查当前元素是否等于其期望的位置,使用数组或列表来存储序列是合适的。我们直接在原数组上统计即可。
  3. 算法步骤

    • 初始化一个变量 cur 表示当前期望的元素值,初始值为1。
    • 遍历原序列 a,对于每个元素 a[i]
      • 如果 a[i] 等于 cur,则说明当前元素是期望的元素,将 cur 增加1。
      • 如果 a[i] 不等于 cur,则说明当前元素需要被删除,记录删除的次数。
    • 遍历结束后,如果 cur 小于等于 n,说明可以找到一个满足条件的子序列,返回删除的次数。
    • 如果 cur 大于 n,说明无法找到满足条件的子序列,返回 -1

代码

public class Main {
    public static int solution(int n, int[] a) {
        int res = 0;
        int cur = 1;
        for (int i = 0; i < a.length; i++) {
            if (a[i] != cur) {
                res++;
            } else {
                cur++;
            }
        }
        return res == a.length ? -1 : res; // placeholder return
    }

    public static void main(String[] args) {
        System.out.println(solution(5, new int[]{1, 4, 2, 3, 5}) == 2);
        System.out.println(solution(3, new int[]{3, 3, 2}) == -1);
        System.out.println(solution(5, new int[]{1, 2, 3, 4, 5}) == 0);
    }
}