array专题3-一道题目不断分析就会慢慢有了思路
#697 Degree of an Array
我承认慢慢有了思路的前提是你要见过那些解法,否则怎么想也想不到。多做题目,就像是多看书一样重要。
问题:一个数组的度=这个数组中出现次数最多元素的出现次数。要找的是最短的子数组,而这个数组的度=原数组的度。
思路一:我肯定需要一次循环,找到数组的度;接着计算每个子数组,计算它们的度,找到和原数组的度相同的最短的子数组。每个子数组就是从下标0开始的子数组,从下标1开始的子数组…。所以有了如下代码。代码时间复杂度O(n^2),发生TLE。
public int findShortestSubArray(int[] nums) {// 数组的度Map<Integer, Integer> countMap = new HashMap<Integer, Integer>();int degree = 0;for (int num : nums) {if (countMap.get(num) == null) {countMap.put(num, 1);} else {countMap.put(num, 1 + countMap.get(num));}degree = Math.max(degree, countMap.get(num));}// 找子数组int minlength = nums.length;for (int start = 0; start < nums.length; start++) {Map<Integer, Integer> subCoutMap = new HashMap<Integer, Integer>();int subDegree = 0;for (int end = start; end < nums.length; end++) {int num = nums[end];if (subCoutMap.get(num) == null) {subCoutMap.put(num, 1);} else {subCoutMap.put(num, 1 + subCoutMap.get(num));}subDegree = Math.max(subDegree, subCoutMap.get(num));if(subDegree == degree){minlength = Math.min(end-start+1, minlength) ;break;}}}return minlength;}
思路二:需要把两层循环改为1层。观察例子中给出的子数组:[1, 2, 2, 3, 1], [1, 2, 2, 3], [2, 2, 3, 1], [1, 2, 2], [2, 2, 3], [2, 2],符合条件的是[2,2]。既然数组的度是由出现次数最多的元素的频次贡献的,那子数组中肯定包含这个元素。要求最短,那子数组的起始元素和结束元素肯定都是这个元素。所以思路改为:
1 需要一次循环,找到数组的度;
2接着再循环找到这个度是由哪个元素贡献的。例如数组 [1, 2, 2, 3, 1]的度是2,是由元素2贡献的。找到2这个元素;
3最后要循环找到这个元素的起止位置,计算子数组的长度。
所以有了如下代码。注意的是:出现次数最多的元素可能不止一个。
public int findShortestSubArrayV2(int[] nums) {// 数组的度Map<Integer, Integer> countMap = new HashMap<Integer, Integer>();int degree = 0;for (int num : nums) {if (countMap.get(num) == null) {countMap.put(num, 1);} else {countMap.put(num, 1 + countMap.get(num));}degree = Math.max(degree, countMap.get(num));}List<Integer> elementList = new ArrayList<Integer>();for(Integer num : countMap.keySet()){if(countMap.get(num)==degree){elementList.add(num);}}int minLength = nums.length;for(int element : elementList){int subDegree = 0;int start = -1;for (int i = 0; i < nums.length; i++) {if(nums[i] == element){if(start == -1){start = i;}subDegree++;if(subDegree == degree){minLength = Math.min(minLength, i-start+1);break;}}}}return minLength;}
思路三:上面的三步有没有可以合并的呢?是不是可以在计算数组的度的时候,顺便记录下每个元素的起止位置呢?当然可以。第二步寻找出现次数等于数组度的元素,和计算子数组长度放在一起。于是有了以下代码。
public int findShortestSubArrayV3(int[] nums) {Map<Integer, Integer> countMap = new HashMap<Integer, Integer>();Map<Integer, Integer[]> numIndexMap = new HashMap<Integer, Integer[]>();int degree = 0;for (int i = 0; i < nums.length; i++) {int num = nums[i];if (countMap.get(num) == null) {countMap.put(num, 1);} else {countMap.put(num, 1 + countMap.get(num));}degree = Math.max(degree, countMap.get(num));if(numIndexMap.get(num)==null){numIndexMap.put(num, new Integer[]{i,i});}else{numIndexMap.get(num)[1] = i;}}int minLength = nums.length;for(int num : countMap.keySet()){if(countMap.get(num) == degree){minLength = Math.min(minLength, numIndexMap.get(num)[1] - numIndexMap.get(num)[0]+1);}}return minLength;}
一步一步改进自己的思路。从最直觉入手。改进的依据是观察标准答案的特征;缩短使用时间。
思路四:看了discuss。两个map合并为一个map,先准备基础数据再计算。不得不说,作者真是牛。作者代码更注重的细节是:Map<Integer,int[]>numMapMap<Integer, int[]> numMapMap<Integer,int[]>numMap 而不是$ Map<Integer, Integer[]> numMap $,我试过了,速度更快。map的get方法尽量调用一次(看我上面代码就知道,我不是这样做的)。作者在最后遍历的是numMap.values(),速度更快。
public int findShortestSubArrayV4(int[] nums) {if (nums.length == 0 || nums == null) return 0;Map<Integer, int[]> numMap = new HashMap<Integer, int[]>();for (int i = 0; i < nums.length; i++) {int num = nums[i];if (numMap.get(num) == null) {numMap.put(num, new int[]{1,i,i});} else {int[] temp = numMap.get(num);temp[0]++;temp[2]=i;}}int degree = 0;int minLength = nums.length;for(int[] values : numMap.values()){if(degree < values[0]){degree = values[0];minLength = values[2]-values[1] +1;}else if(degree == values[0]){minLength = Math.min(minLength, values[2]-values[1] +1);}}return minLength;}
思路5:第二遍刷题。观察到了需要找到出现最多次数元素最左边、最右边的位置。
public int findShortestSubArray(int[] nums) {Map<Integer,Integer> left = new HashMap<Integer,Integer>();Map<Integer,Integer> right = new HashMap<Integer,Integer>();Map<Integer,Integer> count = new HashMap<Integer,Integer>();int degree = 0; for(int i=0;i<nums.length;i++){if(left.get(nums[i])==null) left.put(nums[i],i);right.put(nums[i],i);if(count.get(nums[i])==null)count.put(nums[i],1);elsecount.put(nums[i],count.get(nums[i])+1);degree = Math.max(degree,count.get(nums[i]));}int answer = nums.length;for(Integer num : left.keySet()){if(count.get(num)==degree){answer = Math.min(answer,right.get(num)-left.get(num)+1);}}return answer;}
array专题3-一道题目不断分析就会慢慢有了思路相关推荐
- 由一道题目看抽象向量组的线性相关问题
由一道题目看抽象向量组的线性相关问题 @(数学) 方法:观察法 || 定理 ||过渡矩阵 已知向量组α1,α2,α3\alpha_1,\alpha_2,\alpha_3线性无关,则下面的向量组线性相关 ...
- 由一道题目引发的为稳定与不稳定的排序思路
今天为一道题目伤透了,还是因为自己的脑子不够机灵,很多地方想的不够透彻. 这个一道很典型的排序题目: http://www.cnblogs.com/lveternal/p/3413492.html 这 ...
- 由一道题目总结幂级数的收敛域问题
由一道题目总结幂级数的收敛域问题 @(微积分) 这个知识点可以联想阿贝尔的12块钱,即收敛区间内绝对收敛,边界需要特别讨论. 函数项级数∑∞n=1(2x+1)nn\sum_{n=1}^{\infty} ...
- [SV]SystemVerilog進程之fork join专题详解及案例分析
SystemVerilog進程之fork...join专题详解及案例分析 目錄 一.fork-join 1.1.fork join example, 二.fork-join_ ...
- java 地铁换乘算法,地铁换乘-一道题目,求思路,不求代码,该怎么处理
地铁换乘---一道题目,求思路,不求代码 1.地铁换乘 为解决交通难题,某城市修建了若干条交错的地铁线路,线路名及其所属站名如stations.txt所示. 线1 苹果园 .... 四惠东 线2 西直 ...
- 一道题目入门VMpwn
一道题目学习VMpwn 原理 VMpwn 程序通常都是模拟一套虚拟机,对用户输入的opcode进行解析,模拟程序的执行,故VMpwn常见设计如下: 初始化分配模拟寄存器空间(reg) 初始化分配模拟栈 ...
- 【题解】自己口胡的一道题目
因为从现在到联赛之间我都没法写代码了,我只能用手机看我的博客,看到一道题目,想到强化. 这道题目是luogu4597序列 大意是每次花费1代价给一个数加一或者减一,求把一个数列变成非降的最小代价. 做 ...
- 【2023年电工杯数学建模竞赛】选题分析+A题B题完整思路+代码分享
2023年电工杯B题(附带ChatGpt思路)思路已更新,请点击一下链接 [2023年电工杯数学建模竞赛B题人工智能对大学生学习影响的评价]完整思路分析+完整代码+(附带ChatGpt思路) 1.竞赛 ...
- 安全分析--追踪溯源的找人思路
安全分析–追踪溯源的找人思路 零.绪论: 一旦发生攻击行为,确定攻击者或者说是责任人一般是定损止损快速恢复业务之后的第二反应.谁要为事件负责?谁该承担责任变成了进一步追查的目标.可是在网络攻击行为中能 ...
最新文章
- Webpack-IE低版本兼容指南
- 阿里SopHix热修复框架
- linux 正则查找email_Linux 正则表达式详解
- 滑动窗口最大值—leetcode239
- php根据id查找条件怎么写_thinkphp where()条件查询
- 多线程数据下载(akshare)
- FME中的栅格数据操作之十二——矢量数据栅格化
- 推荐一个Spring Cloud Alibaba 的代码生成器项目
- 云知声打磨四年的AI芯片出炉,中国造芯势力群起
- 积木报表VS睿思BI报表
- Struts 官方下载地址
- 学神、学霸的学生,靠的不是1%的天赋和智商,更不是努力,而是它
- switchhosts使用指南
- 新娘结婚前8天遇害 新郎抱遗照殡仪馆办婚礼
- Oracle的trunc函数与MySQL(Maria)的truncate函数
- 工业品网络营销的第三方平台的免费信息发布:灌水 上海添力
- 邮局选址问题-带权中位数
- 我是CSDN福利狮,今天来给大家发福利!
- 理解Mysql prepare预处理语句
- vue 下拉刷新 组件 伸手党福利
热门文章
- sonyflake.go
- rsync 服务快速部署手册
- 洛谷P3392 涂国旗
- Studio 一些使用
- unity, 同步物体坐标一定要在LateUpdate中进行
- 查看linux的用户
- java args eclipse_不会在eclipse中运行含有args[]参数的Java代码,求指导
- elasticsearch 6.x (五) 单一文档 API 介绍和使用 update和delete API
- lower_case_table_names=1 启动报错 mysql8.0
- 1、vue 笔记之 组件