精华内容
下载资源
问答
  • 中位数 对于有限的数集,可以通过把所有观察值高低排序后找出正中间的一个作为中位数。如果观察值有偶数个,则中位数不唯一,通常取最中间的两个数值的平均数作为中位数中位数寻找的快速算法 一般寻找中位数可以...
    • 中位数

    对于有限的数集,可以通过把所有观察值高低排序后找出正中间的一个作为中位数。如果观察值有偶数个,则中位数不唯一,通常取最中间的两个数值的平均数作为中位数。

    • 中位数寻找的快速算法

    一般寻找中位数可以先将数组排序,按照次序将中间的数据作为中位数即可,其时间复杂度主要取决于排序算法的时间复杂度,利用快速排序可以将其控制为线性对数量级。
    但是能否打破线性对数的限制呢?其中最关键的问题是,寻找中位数并不需要整个数组完全有序,如果把多余的元素排序省略掉,那么就可以超越线性对数的限制实现最快的算法。
    启发来源于快速排序算法中的切分法,比如我们需要找到数组中第 k小的元素,首先将数组a[lo,hi]切分返回整数j,使得 a[lo,j-1]都小于等于a[j],而a[j+1,hi]都大于等于a[j],如果j==k,那么j位置的元素就是我们要找的第k小的元素,而如果j>k,就要切分左子数组,如果j<k,就要切分右子数组,不断缩小选定的子数组的规模直到只剩下一个元素,则它就是最终我们要找的第k小的元素。
    经过数学推导,这种快速切分法寻找中位数仅仅为线性量级,是寻找中位数最为快速的算法。

    • 算法实现
    public class Select {
        // 寻找中位数
        public static <T> Comparable<T> findMedium(Comparable<T>[] a) {
            return select1(a, a.length / 2);
        }
    
        // 找出数组中第k小的元素,非递归实现
        public static <T> Comparable<T> select1(Comparable<T>[] a, int k) {
            int lo = 0, hi = a.length - 1;
            while (hi > lo) {
                int j = partition(a, lo, hi);
                if (j == k) {
                    return a[k];
                } else if (j > k) {
                    hi = j - 1;
                } else if (j < k) {
                    lo = j + 1;
                }
            }
            return a[k];
        }
    
        // 找出数组中第k小的元素,递归实现
        public static <T> Comparable<T> select2(Comparable<T>[] a, int k, int lo, int hi) {
            int j = partition(a, lo, hi);
            if (j == k) {
                return a[k];
            } else if (j > k) {
                return select2(a, k, lo, j - 1);
            } else {
                return select2(a, k, j + 1, hi);
            }
        }
    
        public static <T> int partition(Comparable<T>[] a, int lo, int hi) {
            int i = lo, j = hi + 1;
            Comparable<T> v = a[lo];// 切分元素选为首元素
            while (true) {
                while (less(a[++i], v)) {// 向右扫描
                    if (i == hi) {
                        break;
                    }
                }
                while (less(v, a[--j])) {// 向左扫描
                    if (j == lo) {
                        break;
                    }
                }
                if (i >= j) {// 指针相遇,切分位置确定
                    break;
                }
                exch(a, i, j);// 交换左右逆序元素
            }
            exch(a, lo, j);// 将切分元素放在切分位置
            return j;
        }
    
        @SuppressWarnings("unchecked")
        public static <T> boolean less(Comparable<T> v, Comparable<T> w) {
            return v.compareTo((T) w) < 0;
        }
    
        private static <T> void exch(Comparable<T>[] a, int i, int j) {
            Comparable<T> t = a[i];
            a[i] = a[j];
            a[j] = t;
        }
    
        public static void main(String[] args) {
            String[] a = "qwertyuiopasdfghjklzxcvbnm".split("");
            System.out.println("Max: "+select1(a, 0));
            System.out.println("Min: "+select2(a, 25, 0, a.length - 1));
            System.out.println("Medium: "+findMedium(a));
        }
    }
    展开全文
  • 中位数就是指将数据按大小顺序排列起来,形成一个数列,居于数列中间位置的那个数据就是中位数。 算法思路(1)将输入的n个数划分成 ⌈n5⌉\lceil \frac{n}{5} \rceil 个组,当然最后一组的数目可能是小于5的! ...

    前言

    这一篇文章就上上一篇博文算法的进一步优化了!
    这里我们就利用中位数来进行线性时间的选择算法!

    中位数就是指将数据按大小顺序排列起来,形成一个数列,居于数列中间位置的那个数据就是中位数。

    算法思路

    (1)将输入的n个数划分成 n5 个组,当然最后一组的数目可能是小于5的!
    (2)用任意的排序方法对他们进行排序,并取出一共 n5 个中位数。
    (3)找出该 n5 个中位数中的中位数。(如果 n5 是偶数则取相对大的那个数)
    (4)将全部的数划分为两个部分,小于基准的在左边,大于等于基准的放右边。

    我们用小圆点表示元素,得到如下图:
    选择划分基准

    说明:
    图中中间白色圈表示各组数据的中位数,最中间灰色表示中位数的中位数! 箭头是从较小的数指向较大的数!

    故我们可以使用该数作为划分的基准(比上一个随机基准的方法会好很多)!

    比基准小的数

    图中

    3A1=3(n5)10

    当n≥75时,3A1大于等于14n。所以按此基准划分所得的左右2个子数组的长度都至少缩短14

    代码描述

    int Select(int a[],int p,int r,int k)   
    {  
        if(r-p<75)  
        {  
            //这里对数组 a[p->r] 进行排序 
            return a[p+k-1];  
        }  
        //(r-p-4)/5相当于n-5  
        for(int i=0; i<=(r-p-4)/5; i++)  
        {  
            //这里将元素每5个分成一组,分别排序,并将该组中位数与a[p+i]交换位置  
            //使所有中位数都排列在数组最左侧,以便进一步查找中位数的中位数  
        }  
    
        int x = Select(a,p,p+(r-p-4)/5,(r-p-4)/10);  //找中位数的中位数  
        int i = Partition(a,p,r,x); //以x为基准对数组a进行划分 
    
        int j = i-p+1;  
        if(k<=j)  
        {  
            return Select(a,p,i,k);  
        }  
        else  
        {  
            return Select(a,i+1,r,k-j);  
        }  
    }  
    展开全文
  • 打印1到最大的N位数(递归和非递归解法)

    题目描述:

      输入数字n,按顺序呢打印从1到最大的n 位十进制数,比如输入3,打印1 2 3 。。999

    思路:构造一个二维数组,假如n=3,就构造一个3行的二维数组list

     { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 }

    { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 }

    { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 }

    我们要做的是每次都从第一行,第二行,第三行分别选一个数字打印。  用一个数组 answer来选择 list中 第 i 行选第几列的数字。如answer[2]=3,则表示选择打印 list[2][3]

    代码:

         解法1:

    import java.util.ArrayList;
    
    public class Print1ToMaxN {
    	
    
    	public static void main(String[] args) {
    		// TODO Auto-generated method stub
    		int n = 2;        
    
    		ArrayList<int[]> list = new ArrayList<>(); // 实质是一个二维数组
    		int answer[] = new int[n]; // answer[i] 表示 二维数组中 第 i 行所选的 列 值。 假如
    									// answer[1]=6,
    		// 那么就表示取二维数组 list[1][6]
    
    		int num[] = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 };
    		for (int i = 0; i < n; i++) {
    			list.add(num); // 生成二维数组
    		}
    
    		recursive(0, n, answer, list);
    
    	}
    
    	private static void recursive(int index, int n, int[] answer, ArrayList<int[]> list) {
    		// TODO Auto-generated method stub
    		if (index == n) { // 递归结束条件
    			boolean beginWith0 = true; // 是否是0 开头
    			for (int i = 0; i < n; i++) {
    
    				if (list.get(i)[answer[i]] != 0) {
    					beginWith0 = false;
    				}
    				if (!beginWith0) {
    					System.out.printf("%d", list.get(i)[answer[i]]); // list.get(i)[answer[i]] 表示 list[i][j]
    				}
    
    			}
    			if (!beginWith0) {
    				System.out.println();
    
    			}
    			return;
    		}
    
    		for (answer[index] = 0; answer[index] < 10; answer[index]++) {
    			recursive(index + 1, n, answer, list); // 递归
    		}
    
    	}
    
    }
    

    解法2:  此非递归解法的思想有点类似加法器。

    代码:

    import java.util.ArrayList;
    
    public class numberToPhone1 {
    
    	public static void main(String[] args) {
    		// int num[] = { 0, 1 };
    		int num[] = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 };
    		int n = 3;
    		ArrayList<int[]> list = new ArrayList<>(); // 实质是一个二维数组
    		int answer[] = new int[n]; // answer[i] 表示 二维数组list 中 第 i 行所选的 列 值。
    		
            
    		for (int i = 0; i < n; i++) {
    			list.add(num); // 生成二维数组
    		}
    
    		while (true) {
    			// n为电话号码的长度
    			boolean beginWith0 = true; // 是否是0 开头
    			for (int i = 0; i < n; i++) {
    				if (list.get(i)[answer[i]] != 0) {
    					beginWith0 = false;
    				}
    				if (!beginWith0) {
    					System.out.printf("%d", list.get(i)[answer[i]]);  // list.get(i)[answer[i] 表示 list[i][j]
    				}
    
    			}
    			if (!beginWith0) {
    				System.out.printf("\n");
    			}
    
    			int k = n - 1;
    			while (k >= 0) {
    				if (answer[k] < num.length - 1) {
    					answer[k]++;
    					break;
    				} else {                   // 进位
    					answer[k] = 0;
    					k--;
    				}
    			}
    			if (k < 0)
    				break;
    		}
    
    	}
    
    }
    

    解法3:此解法是剑指offer提供的解法

    代码:

    public class Print1ToMaxN {
    
    	public static void main(String[] args) {
    		// TODO Auto-generated method stub
    		int n = 3;
    		print1ToMaxN(n);
    	}
    
    	private static void print1ToMaxN(int n) {
    		// TODO Auto-generated method stub
    		char number[] = new char[n];
    		recursivePrint(0, number, n);
    	}
    
    	private static void recursivePrint(int index, char[] number, int n) {
    		// TODO Auto-generated method stub
    		if (index == n) {
    			boolean beginWith0 = true;
    
    			for (int i = 0; i < n; i++) {
    
    				if (number[i] != '0') {
    					beginWith0 = false;
    				}
    				if (!beginWith0) {
    					System.out.print(number[i]);
    
    				}
    			}
    
    			if (!beginWith0) {
    				System.out.println();
    
    			}
    
    			return;
    		}
    
    		for (int i = 0; i < 10; i++) {
    			number[index] = (char) ('0' + i);
    			recursivePrint(index + 1, number, n);
    		}
    
    	}
    
    }
    




    测试结果:



    展开全文
  • 排序前数组:453 979 588 279 608 721 677 27...(后面省略n个元素) 第5小的数组元素是:84 排序后数组:18 27 35 52 84 97 102 134 ...(后面省略n个元素)
  • * 程序输出: fibnacci序列的第20个 * 问题分析:采用递归的方法 * 算法设计:略 */ #include using namespace std; int fib(int); //声明函数 int main() { cout(20); //调用 return 0; } ...
    上机内容:C++程序的编写和运行
    上机目的:掌握简单C++程序的编辑、编译、连接和运行的一般过程
    我的程序:
    /* 
    Copyright (c) 2013, 烟台大学计算机学院  
    * All rights reserved.  
    * 作    者:赵玲玲   
    * 完成日期:2013 年 11 月 22 日  
    * 版 本 号:v1.0  
    * 输入描述: 无 
    * 问题描述:设计递归函数,并求出fibnacci序列的第20个数 
    * 程序输出: fibnacci序列中的第20个数
    * 问题分析:采用递归的方法
    * 算法设计:略 
    */  
    
    #include <iostream>
    using namespace std;
    int fib(int);                            //声明函数
    int main()
    {
        cout<<fib(20)<<endl;                 //调用
        return 0;
    }
    int fib(int n)                           //定义
    {
        int sum=0;
        //序列前面四个数比较特殊,单独拿出来
        if(n==1)                             
        {
            return 0;
        }else if(n==2)
        {
            return 1;
        }else if(n==3)
        {
            return 1;
        }else if(n==4)
        {
            return 2;
        }
        //从第5项开始有规律的进行
        else                                 
        {
            sum=fib(n-1)+fib(n-2);            //找规律得到的式子
            return sum;                       //返回
        }
    }
    


    运行结果:
    心得体会:还是不太熟悉递归的调用步骤,这个fib数列的规律也是好歹才找到,后来综合了老师的答案才写出来
    知识点总结:递归的常规运用
    展开全文
  • Java实现 蓝桥杯VIP 算法训练 递归求二进制表示位数

    万次阅读 多人点赞 2019-06-17 07:57:07
    问题描述 给定一个十进制整数,返回其对应的二进制的位数。...输入数据每一个的范围。 例:输入在int表示范围内。 import java.util.Scanner; public class 递归求二进制表示位数 { pub...
  • 为什么你学不会递归?告别递归,谈谈我的经验

    万次阅读 多人点赞 2019-10-27 16:01:40
    可能也有一大部分人知道递归,也能看的懂递归,但在实际做题过程,却不知道怎么使用,有时候还容易被递归给搞晕。也有好几个人来问我有没有快速掌握递归的捷径啊。说实话,哪来那么多捷径啊,不过,我还是想写一篇...
  • bfptr算法(即中位数中位数算法)

    万次阅读 多人点赞 2018-08-25 22:35:16
    BFPRT算法是解决从n个数中选择第k大或第k小的这个经典问题的著名算法,但很多人并不了解其细节。本文将首先介绍求解这个第k小数字问题的几个思路,然后重点介绍在最坏情况下复杂度仍然为O(n)的BFPRT算法。 一 ...
  • 100亿个整数,找出中位数

    千次阅读 2017-07-26 10:50:51
    100亿个整数,内存足够,如何找到中位数?内存不足,如何找到中位数?... • 如果小于它的数超过一半,那么中位数一定在左半边,递归到左边处理(还是第几大) • 否则中位数一定在右半边,根据左半边的元素个数
  • 算法导论 9.3-8 求两个数组的中位数

    千次阅读 热门讨论 2012-06-25 09:06:58
    设X[1..n]和Y[1..n]为两个数组,每个都包含n个已排好序的数,给出一个求数组X和数组Y中所有2n个元素的中位数的O(lgn)时间的算法 二、思路 递归求解该问题,解题规模不断减半,最后剩下4个元素时,得到问题的解, ...
  • 计算两个有序数组的中位数

    千次阅读 2018-09-04 11:56:01
    题目: ...类比一个数组的中位数,求两个数组的中位数就相当于把两个数组合并后的一个数组的中位数,例 输入: num1=[1,3,5] num2=[2,4,6] 输出:(3+4)/2=3.5   方法:二分+递归 思路: --...
  • BFPRT(中位数中位数)算法

    千次阅读 2017-10-09 16:05:05
    BFPRT 算法又称为 “中位数中位数算法”,该算法由 Blum、Floyd、Pratt、Rivest、Tarjan 在1973年提出,最坏时间复杂度为 O(n) TOP-K问题
  • 主要思想:设置两个游标,start,end,取start和end的中位数,及其左边一位,和右边一位,将三者与目标值的绝对差值进行比较。设中位数与目标的绝对差值为sm,左边一位的绝对差值为sl,右边一位的绝对差值为sr,对...
  • Java实现 LeetCode 4 寻找两个有序数组的中位数

    万次阅读 多人点赞 2020-02-11 18:54:06
    寻找两个有序数组的中位数 给定两个大小为 m 和 n 的有序数组 nums1 和 nums2。 请你找出这两个有序数组的中位数,并且要求算法的时间复杂度为 O(log(m + n))。 你可以假设 nums1 和 nums2 不会同时为空。 示例 1: ...
  • 线性时间的中位数查找算法

    千次阅读 2015-04-16 09:59:32
    一般来说,中位数的查找算法都是基于先排序,后找中间位置的数字的算法,但是因为线性时间排序所收到的限制比较大,而如果使用基于比较的排序,时间复杂度将至少为O(nlogn),如何以线性时间完成中位数或者数组中第N...
  • 递归

    2014-04-10 00:32:48
    日积月累第四周第三天...递归做为一种算法在程序设计语言广泛应用。 一个过程或函数在其定义或说明有直接或间接调用自身的一种方法,它通常把一个大型复杂的问题层层转化为一个与原问题相似的规模较小的问题来求
  • java的方法递归

    千次阅读 多人点赞 2020-12-06 17:32:58
    JAVA的方法递归 递归的思路 代码举例 一、递归的思路 一个方法在执行时,调用自身被称为“递归”。 递归相当于数学归纳法,有一个起始条件,有一个递推公式。 递归可以分为:单路递归和多路递归(如二叉树和...
  • c#递归求斐波那契数列第N位数

    千次阅读 2019-02-13 16:26:59
    斐波那契数列由两个 1 开端,其后的每一数字都是前两数字之和。譬如 1 和 1 的和为 2,1 和 2 的和为 3,2 和 3 的和为 5,3 和 5 的和为 8……一直这样继续计算下去,就得到下面这样的数列。 1, 1, 2, 3, 5, 8,...
  • lintcode两个排序数组的中位数

    千次阅读 2017-08-31 18:41:27
    两个排序数组的中位数   描述 笔记  数据  评测 两个排序的数组A和B分别含有m和n个数,找到两个排序数组的中位数,要求时间复杂度应为O(log (m+n))。 您在真实的面试中是否遇到过...
  • 问题:设X[0:n-1]和Y[0:n-1]为两个数组,每个...简单来说,就是比较两个区间的中位数,如果第一个区间的中位数比第二个大,那么就把第一个区间的范围缩小至它的前半段,把第二个区间缩小至它的后半段,然后重复上述过
  • C++ 数字反向(递归与非递归实现)

    千次阅读 2018-11-24 16:28:18
    数字反向:函数接收一个整数值,返回这个数中数字逆序后的结果值。例如输入1234,输出4321. 实现代码 #include&amp;lt;iostream&amp;gt; using namespace std; int reverseNum(int );//函数原型 void ...
  • 我前几天忘记突然想到如何借用系统栈逆置一个整数,逆置一个单链表。...想一想递归函数体应该有什么 ? 递归出口。递归不能无限递归,否则会stackoverflow 递归函数。 下一次递归下去的函数参数,根据条件,设...
  • 中位数O(n)算法

    万次阅读 2015-07-21 10:09:29
    中位数是排序后数组的中间值,如果数组的个数是偶数个,则返回排序后数组的第N/2个数。 样例 给出数组[4, 5, 1, 2, 3], 返回 3 给出数组[7, 9, 4, 5],返回 5 解题思路: 利用快排划分的思想,递归...
  • 内存足够的情况: 可以使用类似quick sort的思想...• 如果小于它的数超过一半,那么中位数一定在左半边,递归到左边处理  • 否则,中位数一定在右半边,根据左半边的元素个数计算出中位数是右半边的第几大,然后
  • 算法设计实验--中位数问题

    千次阅读 2019-03-12 18:54:05
    中位数问题 两个相同大小的有序数组,求此2n个数的中位数。 大体思路: 分别求出两数组中的中位数并进行比较 1,若相等,则即为所求; 2,如果x数组中的中位数大于y数组中的中位数,则进一步在x数组的后半段和y...
  • lintcode - 用递归打印数字

    千次阅读 2016-09-01 10:33:29
    题目描述:用递归的方法找到从1到最大的N整数。 样例: 给出 N = 1, 返回[1,2,3,4,5,6,7,8,9]. 给出 N = 2, 返回[1,2,3,4,5,6,7,8,9,10,11,...,99]. 题目要求用递归的方法。那就先来看一下,当N = i 和 N = ...
  • 用汇编语言递归方法找出斐波那契数列的对应位数 .MODEL SMALL .DATA STRING1 DB 'PLEASE INTPUT THE NMBER:$'; 请输入你想知道的第几个斐波那契数列 STRING2 DB 'THE RESULT:$'; 这个结果是 .CODE main...

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 190,428
精华内容 76,171
关键字:

中位数递归