本文主要是介绍滑动窗口——632. 最小区间,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!
最近在抽时间写LC上的一个专栏——2024春招冲刺百题计划。挑着做,做了几道和滑动窗口相关的题目,632. 最小区间,LC上标记为困难,第一次写完全没有思考,参考了别人写的答案茅塞顿开,特此记录以鞭策自己学习。最近实习结束回到学校后,一边搞科研,自己本来想一天写一篇博客,以此鞭策自己学习,但自己研究方向和后端丝毫不沾边,自己最近又没有学习新的知识用以记录博客,也甚是悔已。人生如是,时常悔已。
题目简介
632. 最小区间
题目分析
第一眼看到这个题目让我感到非常陌生,此前并没有遇到过此种类型的题目,想了一会写了一种非常简单的实现,特别离谱就不写出来了。记录一下别人的做法,仅供加深学习印象。
题目要的是找到一个最小的区间,对于这个区间的要求就是必须包含每个区间的至少一个元素。可以将区间个数作为限制条件,一共cnt = nums.size()个区间,这个个数作为滑动窗口的限制条件。【与此前的滑动窗口限制条件均为区间不同,应该加以变通】
如何实现上面的区间个数作为滑动窗口的限制条件呢?大佬们提供了一种异常简洁的做法,将原本的二维List转换为一个二维数组arrs,对于二维数组中的每一个元素 arrs[i][0] 表示对应的元素值,arr[i][1] 表示对应的元素值属于原本的二维List的第几个list集合。通过转换将二维List完美转换为了数组。
构建arrs数组后对数组按照元素值进行升序排序。排序是否必须的,只有通过排序才能够使得元素值由小到大排列,相近大小元素位置相近,此时才符合题目找出最小区间的约束。
随后以区间个数作为滑动窗口限制条件,当窗口内的区间个数满足条件后,不断缩小左边界,以寻得符合条件的最小区间。
具体见代码实现,已经注释过的。
代码编写
class Solution {public int[] smallestRange(List<List<Integer>> nums) {// 滑动窗口实现NBint total = 0;for(List<Integer> num : nums){total += num.size();}// 创建二维数组存储, arr[i][0]代表第i个元素的值,arr[i][1]代表第i个元素原先位于的组int[][] arr = new int[total][2];int i = 0, j = 0;for(List<Integer> num : nums){for(int nm : num){arr[i][0] = nm;arr[i][1] = j;++i;}++j;}// 对创建的二维数组排序Arrays.sort(arr, (o1, o2)-> o1[0] - o2[0]);// 创建返回的数组int[] ans = new int[2];// 创建数组记录每组中的元素出现的次数int[] count = new int[nums.size()];for(int l = 0, r = 0, k = 0; r < total; r++){if(0 == count[arr[r][1]]++){++k;}if(k == nums.size()){while(count[arr[l][1]] > 1){count[arr[l++][1]]--;}if((ans[0] == 0 && ans[1] == 0) || ans[1] - ans[0] > arr[r][0] - arr[l][0]){ans[0] = arr[l][0];ans[1] = arr[r][0];}}}return ans;}
}
/*
a b c d4 10 15 24 260 9 12 205 18 22 30*/
这篇关于滑动窗口——632. 最小区间的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!