LeetCode高频题:最少经过几次操作可以使数组变为非降序状态

编程入门 行业动态 更新时间:2024-10-11 15:24:55

LeetCode高频题:最少经过<a href=https://www.elefans.com/category/jswz/34/1767511.html style=几次操作可以使数组变为非降序状态"/>

LeetCode高频题:最少经过几次操作可以使数组变为非降序状态

LeetCode高频题:最少经过几次操作可以使数组变为非降序状态

提示:本题是系列LeetCode的150道高频题,你未来遇到的互联网大厂的笔试和面试考题,基本都是从这上面改编而来的题目
互联网大厂们在公司养了一大批ACM竞赛的大佬们,吃完饭就是设计考题,然后去考应聘人员,你要做的就是学基础树结构与算法,然后打通任督二脉,以应对波云诡谲的大厂笔试面试题!
你要是不扎实学习数据结构与算法,好好动手手撕代码,锻炼解题能力,你可能会在笔试面试过程中,连题目都看不懂!比如华为,字节啥的,足够让你读不懂题

基础知识:
【1】LeetCode高频题300. 最长递增子序列


文章目录

  • LeetCode高频题:最少经过几次操作可以使数组变为非降序状态
    • @[TOC](文章目录)
  • 题目
  • 一、审题
  • 了解一下最长递增子序列
  • 再想新的办法
    • 这是啥原理呢???
  • 给你一个数组arr,最长连续递增子序列的长度怎么求?
  • 然后我们来破解原题!
  • 总结

题目

作者:牛客40502855号
来源:牛客网

给定一个大小为N的无序数组arr,对数组中的每个元素可进行如下操作:
将元素移动至数组的头部
将元素移动至数组的尾部
注意:这里的移动不是通过元素的交换完成的,而是直接将元素移动到指定位置,空出来的位置由别的元素顺次填满。
问:最少经过几次操作可以使数组变为非降序状态。


一、审题

输入:
第一行输入一个正数n代表数组arr的元素个数
第二行,给出n个正整数ai,代表数组中的元素
1<=n<=3*10的5次方
1<=ai<=10的9次方

输出:
一个数ans,代表将数组操作为非降序状态所需的最小次数

比如
arr=19 7 8 25
首先8移动到首部
arr=8 19 7 25
然后将7移动到首部
7 8 19 25

2次就搞定了


了解一下最长递增子序列

19 7 8 25
最长的非递减子序列长度是3
N总长度=4
N-3=1
实际上却需要移动2次,怎么解释呢?

要不整一个范围上的尝试???
设f(i)是将i位置元素调整之后,所需要的最少操作次数

主函数调用f(0位置开始),直到i到N位置越界,看看最少调整次数是?

那么我们来讨论一波,这个f怎么写才好

(0)当i=N越界时,不需要调动,操作0次,返回0次即可
(1)任意位置i时:可以让i位置不动,算操作0次,看看f(i+1)
(2)任意位置i时:可以让i位置去首部,算操作1次,剩下的arr,看看f(i+1)
(3)任意位置i时:可以让i位置去尾部,算操作1次,剩下的arr,看看f(i+1)
这三者的答案,选择最小值返回

中间动过的arr,需要我们带着玩???
这么做可以,但是这是极其不好的尝试办法,因为arr一直变动,而且不是简单的变量类型,这种方法,蠢!

再想新的办法

据说先排序:

需要一个大小为n的数组记录排好序的结果,
然后挨个比较,统计排序数组对应原数组的下标数组,它的最长递增子序列,
最后用n减去这个序列长度

比如上面的19 7 8 25
7 8 19 25这个排序数组对应原数组的索引下标数组为
1 2 0 3,找到1203最长连续递增子数组即可
——不连续的还不行【因此我们说的基础知识【1】还不能用】

之前求过最长递增子序列的长度——这里是不连续的哦!!!【是一个贼难的题目】
【1】LeetCode高频题300. 最长递增子序列

1 2 或者0 3 构成最长连续的递增子序列,构成的2长度
故,原数组需要动几次呢?4-2=2次

没错,就是这样干

这是啥原理呢???

你最终就是想要把arr变为非递减状态,

那么原数组排序后,位置不动的最长连续递增那一堆,是我们不需要移动的位置,你想想是不是
19 7 8 25
排序后,是7 8 19 25
78 19 是动过得,但是因为19 移动到右边,然后25移动到右边就自动OK了,那么7 8是我们不需要移动的数
因此动就是要动4-2的长度

这,很难想到

OK,方法是很难想到,蔚来考的笔试题,现场3个题都很难,因此没人做出来
只能线下慢慢想,见过可能下次就会了……

我们谢谢代码!

给你一个数组arr,最长连续递增子序列的长度怎么求?

1 2 0 3
最长连续递增,既然是连续的

那就考虑以i结尾的子数组,它最长连续递增长度是多少?
实际上就是填一个表dp[i]表示以i结尾的子数组,长度是多少?

对于dp[i],只要是[i]>[i-1],dp[i]=do[i-1]+1,否则就是1

中途将最大值更新给max即可

手撕代码:

    //实际上就是填一个表dp[i]表示以i结尾的子数组,长度是多少?public static int longestConsecutiveArrLen(int[] arr){if (arr == null || arr.length == 0) return 0;if (arr.length == 1) return 1;int N = arr.length;int max = 1;//至少1int[] dp = new int[N];//dp[i]表示以i结尾的子数组,长度是多少//先都是1for (int i = 0; i < N; i++) {dp[i] = 1;//最次就是自己}for (int i = 1; i < N; i++) {//从1位置看,只要是严格大于前面的位置,就算OKdp[i] = arr[i] > arr[i - 1] ? dp[i -1] + 1 : 0;max = Math.max(max, dp[i]);}return max;}public static void test(){int[] arr = {1,2,0,3};System.out.println(longestConsecutiveArrLen(arr));}public static void main(String[] args) {test();}

测试:2
问题不大,这只要是连续的就行了好说

然后我们来破解原题!

输入:
第一行输入一个正数n,代表数组arr的元素个数
第二行,给出n个正整数ai,代表数组中的元素

输出:
一个数ans,代表将数组操作为非降序状态所需的最小次数

原始数组arr,排序后为arr2
还需要用数组map记录排序后arr2对应到原始数组arr的下标位置

我们排序之后还要知道下标,就需要打包一个节点,把读进来的arri和下标i放一个节点
还要准备比较器,用arri的val排序,升序

        //加装下标public static class Node{public int val;public int index;//下标public Node(int v, int i){val = v;index = i;}}//比较器public static class cptr implements Comparator<Node> {@Overridepublic int compare(Node o1, Node o2){return o1.val - o2.val;//升序}}

okay,正式手撕本题的代码:

public static void main(String[] args) {Scanner in = new Scanner(System.in);// 注意 hasNext 和 hasNextLine 的区别int N = in.nextInt();Node[] arr = new Node[N];for (int i = 0; i < N; i++) {int val = in.nextInt();arr[i] = new Node(val, i);//包装好放入arr}Arrays.sort(arr, new cptr());//排序//整一个节点装下标吧int[] ids = new int[N];for (int i = 0; i < N; i++) {ids[i] = arr[i].index;//把位置搞出来,然后查最长递增子数组的长度}int max = longestConsecutiveArrLen(ids);int ans = N - max;System.out.println(ans);}

无法就是读取arri,把arri和i包装为node
然后排序node
然后把下标ids读出来
用我们上面准备好的最长严格递增子序列的求解函数,把ids的最长递增长度求出来
然后N-max就是结果了

测试:

6
6 5 4 3 2 1
5
4
19 7 8 25
2

问题不大

整体时间复杂度在排序那o(nlog(n))


总结

提示:重要经验:

1)本题难就难在怎么想解法,你要将其变为非递减状态,原来那个数组排序后位置动过的最长递增那个子数组,是不需要动的,它的长度就是不动的长度
2)N-这个最长严格递增子序列长度就是我们要动的其他位置,难想但是见过,下次就明白了
3)另外,我们不求这个题,单独求最长递增子序列长度怎么求,那个题很经典,也很困难,要学学
3)笔试求AC,可以不考虑空间复杂度,但是面试既要考虑时间复杂度最优,也要考虑空间复杂度最优。

更多推荐

LeetCode高频题:最少经过几次操作可以使数组变为非降序状态

本文发布于:2024-02-06 15:22:53,感谢您对本站的认可!
本文链接:https://www.elefans.com/category/jswz/34/1749780.html
版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系,我们将在24小时内删除。
本文标签:几次   数组   状态   操作   降序

发布评论

评论列表 (有 0 条评论)
草根站长

>www.elefans.com

编程频道|电子爱好者 - 技术资讯及电子产品介绍!