从求数组Top N个数开始说起的求数组的若干问题笔记
2015-01-12 21:29
106 查看
随便百度看到有博客关于求数组的最大N个数的问题的文章,想起好像在编程之美上有这么一道题,好多天没有练练数据结构的题目,就从求数组的最大K个数说起。
关于这道题目编程之美提供了很多种算法,此处受插入排序的启发,提供一种改进的插入排序算法如下,最坏时间复杂度为O(n * m),空间复杂度为1.提供实现代码如下:
以上解法自我感觉运用了点小技巧,通过插入排序的启发,此处对数组m中前n个元素进行插入排序,n个元素之后只需要维护前n个元素最大有序就行,则插入排序完成后,取前n个元素就是最大的n个元素。翻看编程之美的多种解法,最后百度的时候看到CSDN的v_JULY_v大神的一篇文章程序员编程艺术:第三章续、Top
K算法问题的实现 对求数组的最大K个数的深入解读,深刻感受大牛到底厉害在哪里,大牛对待编程艺术的严谨和深入,在此,对v_JULY_v大神的系列博客膜拜一次。
求完数组的最大N个数后,我也来一次举一反三,那取数组的任意N个数情况该怎么处理,以下针对求数组{1,3,4,6,7,2}的任意3个数的所有组合给出自己不成熟的解答,此处的实现思路如下:
我们可以设定数组{1,3,4,6,7,2}取出的元素按数组的索引从小到大去取,因此,我们第一个数取1的话,取第二个数只能从{3,4,6,7,2} 取,取完第二个数,第三个数只能从剩下的去取。我们知道,我们取第一个数可以取{1,3,4,6},实际在取数组的时候对从索引0 到 数组长度 length -n +1取。
Q2:求数组{1,3,4,6,7,2}的3个数的所有组合, 代码实现如下:
针对以上解法,我们发现当我们随机取的N比较大的时候,我们的for循环有N此之多,可知以上算法不可取,针对每次循环的规律和for,我想大家会马上想到,for循环改成递归调用,代码量就会小不少。
Q2改进: 递归求数组的任意N个数的所有组合,代码实现如下:
以上求完数组{1,3,4,6,7,2}的3个数的实现,我们再来举一反三,再来变化下题目的条件,我们来求n个数组任意选取一个元素的所有组合,针对以上的递归解法,我们发现求n个数组任意选取一个元素的所有组合变的很简单,实现思路如下:
我们递归的最外层,我们取第一个数组,我们可以循环遍历取任何一个元素,然后我们递归时候 取第二个数组,我们再次循环遍历取任意一个元素,依次循环下去,当我们循环取到数组集合的最后一个数组时,我们的最内层循环结束。此时,读出我们每一层循环的数组就是所有的情况。以下给出代码实现如下:
Q3: n个数组任意选取一个元素的所有组合,代码实现如下:
关于这道题目编程之美提供了很多种算法,此处受插入排序的启发,提供一种改进的插入排序算法如下,最坏时间复杂度为O(n * m),空间复杂度为1.提供实现代码如下:
void GetMaxList(int[] m,int n){//此算法为插入排序的启发 if(m == null || m.length < n) return ; for(int i = 1;i<m.length;i++){ int j; if(i < n){ //此处判断的目的一直保证前N个数字有序 j = i-1; }else{ j = n-1; } int temp = m[i]; while(j >= 0 && m[j] < temp){ m[j+1] = m[j]; j--; } if(j != i-1) m[j+1] = temp; } for(int i = 0;i<n;i++ ){ System.out.print(m[i] + "\t"); } }
以上解法自我感觉运用了点小技巧,通过插入排序的启发,此处对数组m中前n个元素进行插入排序,n个元素之后只需要维护前n个元素最大有序就行,则插入排序完成后,取前n个元素就是最大的n个元素。翻看编程之美的多种解法,最后百度的时候看到CSDN的v_JULY_v大神的一篇文章程序员编程艺术:第三章续、Top
K算法问题的实现 对求数组的最大K个数的深入解读,深刻感受大牛到底厉害在哪里,大牛对待编程艺术的严谨和深入,在此,对v_JULY_v大神的系列博客膜拜一次。
求完数组的最大N个数后,我也来一次举一反三,那取数组的任意N个数情况该怎么处理,以下针对求数组{1,3,4,6,7,2}的任意3个数的所有组合给出自己不成熟的解答,此处的实现思路如下:
我们可以设定数组{1,3,4,6,7,2}取出的元素按数组的索引从小到大去取,因此,我们第一个数取1的话,取第二个数只能从{3,4,6,7,2} 取,取完第二个数,第三个数只能从剩下的去取。我们知道,我们取第一个数可以取{1,3,4,6},实际在取数组的时候对从索引0 到 数组长度 length -n +1取。
Q2:求数组{1,3,4,6,7,2}的3个数的所有组合, 代码实现如下:
public static void main(String[] args) { int[] numArr = {1,3,4,6,7,2}; int n = 3; getMaxNList(numArr,n); } static void getMaxNList(int[] numArr,int n){ int[] result = new int ; for(int i =0;i< numArr.length - n+1;i++){ result[0] = numArr[i]; for(int j = i+1;j<numArr.length - n +2;j++){ result[1] = numArr[j]; for(int k = j+1;k<numArr.length-n+3;k++){ result[2] = numArr[k]; print(result); } } } } static void print(int[] result){ for(int num : result){ System.out.print(num); System.out.print(" "); } System.out.println(); }输出结果如下:
1 3 4 1 3 6 1 3 7 1 3 2 1 4 6 1 4 7 1 4 2 1 6 7 1 6 2 1 7 2 3 4 6 3 4 7 3 4 2 3 6 7 3 6 2 3 7 2 4 6 7 4 6 2 4 7 2 6 7 2
针对以上解法,我们发现当我们随机取的N比较大的时候,我们的for循环有N此之多,可知以上算法不可取,针对每次循环的规律和for,我想大家会马上想到,for循环改成递归调用,代码量就会小不少。
Q2改进: 递归求数组的任意N个数的所有组合,代码实现如下:
public static void main(String[] args) { int[] numArr = {1,3,4,6,7,2}; int n = 3; getMaxNList(numArr,n); } static void getMaxNList(int[] numArr,int n){ int[] result = new int ; loopMaxNList(numArr,0,0,n,result); } static void loopMaxNList(int[] numArr,int startIndex, int curIndex,final int num,int[] result){ if(curIndex < num ){ //递归结束条件,当前result给元素赋值索引等于result的长度 for(int i = startIndex;i < numArr.length - num + curIndex + 1;i++){ result[curIndex] = numArr[i]; loopMaxNList(numArr,i+1,curIndex+1,num,result); } }else{ //最内层递归结束时,读出所有元素 print(result); } } static void print(int[] result){ for(int num : result){ System.out.print(num); System.out.print(" "); } System.out.println(); }
以上求完数组{1,3,4,6,7,2}的3个数的实现,我们再来举一反三,再来变化下题目的条件,我们来求n个数组任意选取一个元素的所有组合,针对以上的递归解法,我们发现求n个数组任意选取一个元素的所有组合变的很简单,实现思路如下:
我们递归的最外层,我们取第一个数组,我们可以循环遍历取任何一个元素,然后我们递归时候 取第二个数组,我们再次循环遍历取任意一个元素,依次循环下去,当我们循环取到数组集合的最后一个数组时,我们的最内层循环结束。此时,读出我们每一层循环的数组就是所有的情况。以下给出代码实现如下:
Q3: n个数组任意选取一个元素的所有组合,代码实现如下:
public static void main(String[] args) { List<int[]> arrList= new ArrayList<int[]>(); arrList.add(new int[]{1,5,9}); arrList.add(new int[]{2,4}); arrList.add(new int[]{6,8,3}); getResult(arrList); } static void getResult(List<int[]> arrList){ int n = arrList.size(); int[] result = new int ; getNum(arrList,result,n,0); } static void getNum(List<int[]> arrList,int[] result,int n,int curIndex){ if(curIndex < n){ //递归结束条件,当前已经在每一个数组都已经取了一个元素 int[] arr = arrList.get(curIndex); for(int i = 0;i<arr.length;i++){ result[curIndex] = arr[i]; getNum(arrList,result,n,curIndex+1); } }else{ //递归结束时候打印出数组 print(result); } } static void print(int[] result){ for(int num : result){ System.out.print(num+"\t"); } System.out.println(); }我们可知我们的输出所有组合应该是3*2*3 = 18种。我们的输出如下:
1 2 6 1 2 8 1 2 3 1 4 6 1 4 8 1 4 3 5 2 6 5 2 8 5 2 3 5 4 6 5 4 8 5 4 3 9 2 6 9 2 8 9 2 3 9 4 6 9 4 8 9 4 3
相关文章推荐
- JNI学习笔记5——本地方法处理java数组/引用问题/缓存jfieldID/jmethodID
- java笔记:关于复杂数据存储的问题--基础篇:数组以及浅拷贝与深拷贝的问题(下)
- 关于iOS UITableView 数据源数组加载完成之后,滑动时出现cell为空的问题解决笔记
- [笔记]关于split的数组越界问题以及java.lang.ArrayIndexOutOfBoundsException异常
- Eclipse下LogCat打印信息瞬间消失了,以及byte数组转字符串是出现多余的空格问题的解决方案(随手小笔记)
- 关于sql语句中top + order by语句出现多提取问题的解决[cherryt笔记]
- 关于数据类型与指针的小笔记--初始化问题&&数组
- C语言一级指针、二级指针、数组作为参数传递需要注意的若干问题
- MPI并行编程传递多维数组需要注意的若干问题
- 重温《C++ Primer》笔记八 数组与指针的几个问题
- java笔记:关于复杂数据存储的问题--基础篇:数组以及浅拷贝与深拷贝的问题(上)
- 将List转化为数组的若干问题
- 【Java学习笔记】Day 1 String类的学习及堆栈的若干问题 (待整理)
- 给定一个数组,按序排列,从数组找出若干个数,使得这若干个数字的和与M最为接近,(背包问题)
- MySQL的安全问题从安装开始说起
- java笔记:关于复杂数据存储的问题--基础篇:数组以及浅拷贝与深拷贝的问题(上)
- python学习笔记:二维数组排序问题
- 关于C++动态数组的若干问题
- 一段高质量的SQL从问问题开始(笔记)
- 学习笔记——ajax传值数组对象中遇到的问题