在一个int数组里查找出所有这样的数,它大于等于左侧所有数,小于等于右侧所有数。

http://www.chongchonggou.com/g_469012414.html

这题很直观的一个算法是,挨个的查找各个元素是否满足条件,算法的复杂度是O(n^2),太过复杂。 但如果我们在从左到右扫描数组的时候,能够维护一个candidate的数组, 该数组的元素满足: 到目前为止,这些元素都大于等于它前面的元素,而小于等于到目前为止扫描到的它右边的所有元素。 容易证明, candidate数组中的元素是按照非递减顺序排列的,即对任意的i<j有cand[i] <= cand[j]. 当我们扫描到一个小的元素的时候,需要从右到左(从大到小)的判断cand数组中的元素是否还满足条件,知道找到第一个不大于当前扫面元素的cand.

下面是算法的实现(原文为cpp代码):

public class test {
    public static int findNum(int[] arr, int n) {
        if (arr == null)
            return 0;
        int[] cand = new int[n];
        int idx = 0; // 记录当前cand数组中的元素个数。
        cand[idx++] = arr[0];
        int max = arr[0], i;
        for (i = 1; i < n; i++) {
            if (arr[i] >= max) {
                cand[idx++] = arr[i];
                max = arr[i];
            } else {
                while (idx > 0 && cand[idx - 1] > arr[i])
                    idx--;
            }
        }
        System.out.println("num: ");
        for (i = 0; i < idx; i++)
            System.out.print(cand[i]);
        System.out.print("\n");
        return idx;
    }

    public static void main(String args[]) {
        int[] arr = { 3, 1, 6, 4, 5, 7, 9, 8, 10, 14, 12 };
        // int[] arr = { 1, 2, 4, 5, 6, 7, 8, 9, 10, 3, 11 };
        int count = 0;
        count = findNum(arr, 11);
        System.out.println("count: " + count);

    }
}

整个算法只需要对原来的数组扫描一次, 并且每个元素进入或者退出candidate数组最多一次。 算法在最坏情况下最多进行比较2*n次,时间和空间复杂度都是O(n).

Similar Posts:

  • 微软面试100题(93):数组里查找大于等于左侧所有数小于等于右侧所有数的数

    在一个int 数组里查找这样的数,它大于等于左侧所有数,小于等于右侧所有数. 这个题目到手直观感受是相当于一轮快排.所以对原数组进行快排,完成后的序列和新序列如果值相等,那么说明该数满足条件. 文中的解答如下: 直观想法是用两个数组a.b.a[i].b[i]分别保存从前到i 的最大的数和从后到i 的最小的数,一个解答:这需要两次遍历,然后再遍历一次原数组,将所有data[i]>=a[i-1]&&data[i] 该算法优化仅需不记录最小值数组,只记录当前最小值,并且符合条件直接输出即可

  • 从数组中查找出最大最小两数的log(n)算法

    从一个数组中选择出最大和最小两个数的一般实现方法是从数组第一个元素到最后一个挨个比较,用两个数分别记录max.min,时间复杂性为O(n).其实还有效率更高的方法,下面将介绍的方法时间复杂性为O(log(n)) [cpp] view plaincopy #include <stdio.h> void maxmin(int a[],int i, int j, int *max, int *min){ int m,_max1,_min1,_max2,_min2; if(i == j) { *max

  • [置顶] 给出洗牌的一个算法,并将洗好的牌存储在一个整形数组里。(思路2)

    给出洗牌的一个算法,并将洗好的牌存储在一个整形数组里. (思路2) 本题的解决办法是:先将1到54张牌有序的存储在一个数组中,然后每次随机交换数组中的两个数字. 该算法的空间复杂度O(n),时间复杂度是根据交换的次数,理论上来说,交换次数越多,数组中的数就越随机.但是个人觉得,一般能有50次左右的交换,就能达到随机的要求了. (然后经过一些深入的思考和网上查找到的数据显示,从数学上来说,要使牌充分随机的话,那么任意一张牌都要充分的移动,换句话说,就是要使任意一张牌没有被抽到的概率非常非常小,经过

  • 一组数字,从1到n,从中减少了3个数,顺序打乱,放在n-3的数组里,找出丢失数字

    曾经看到有这样一个JS题: 有一组数字,从1到n,从中减少了3个数,顺序也被打乱,放在一个n-3的数组里 请找出丢失的数字,最好能有程序,最好算法比较快 假设n=10000 下面我也来贴一个算法. function getArray (){ //创建随机丢失3个数字的数组,并打乱顺序. var arr =[] for(var i=1;i<=10000;i++){ arr.push(i); } var a = arr.splice(Math.floor(Math.random()*arr.leng

  • 第十四题:在一个排序数组中查找一对数,使得其和等于某个值

    /* ============================================================================ 题目:输入一个已经按升序排序过的数组和一个数字, 在数组中查找两个数,使得它们的和正好是输入的那个数字. 要求时间复杂度是O(n).如果有多对数字的和等于输入的数字,输出任意一对即可. 例如输入数组1.2.4.7.11.15和数字15.由于4+11=15,因此输出4和11. ================================

  • 从一个无序的数组中查找二个遗漏的数

    一个包含98个元素的数组,存储了1-100中的98个数字,除了1个以外,这98个数字是乱序 排列的.现让你找出到底缺的是哪个数字,要求: 1)只能遍历一次: 2)除了数组本身以外,只有2个整数单元的额外存储空间. import java.util.*; import java.io.*; /** *//** * <p>Title: </p> * <p>Description: </p> * <p>Copyright: Copyright (c)

  • 额外数组____O(n)寻找&amp;gt;=左侧所有数,&amp;lt;=右侧所有数

    使用额外数组,比如rightMin[],来帮我们记录原始数组array[i]右边(包括自己)的最小值. 假如原始数组为: array[] = {7, 10, 2, 6, 19, 22, 32}, 那么rightMin[] = {2, 2, 2, 6, 19, 22, 32}. 也就是说,7右边的最小值为2, 2右边的最小值也是2. 有了这样一个额外数组,当我们从头开始遍历原始数组时,我们保存一个当前最大值 max, 如果当前最大值刚好等于rightMin[i], 那么这个最大值一定满足条件.还是

  • 常见算法题系列(四):在循环有序数组中查找指定元素

    问题描述:我们都知道,在一个有序数组中查找指定的元素可以使用二分法.那么对于一个循环有序的数组该怎样进行查找呢? 这里所说的循环有序数组,就是把一个有序数组从某个(未知)位置处截为两段,把前一段放到后一段的后面(数组里的元素还是有序的,只不过最小值不一定是数组的第一个元素,而可能是其中的任何一项,从它开始逐项递增,到数组的最后一个元素时再回到第一个元素). 显然传统的二分法已经无法直接使用了,但考虑一下,如果已经知道分界点位置,那问题就简单多了,只要先判断一下待查元素是在分界点的左侧还是右侧,然

  • :输入10个整数,保存在一个数组中,在数组中查找某个数,给出是否找到的信息。如果找到了,要求输出该数在数组

    题目:输入10个整数,保存在一个数组中,在数组中查找某个数,给出是否找到的信息.如果找到了,要求输出该数在数组中所处的位置:如果找不到,输出"没有找到!". 解析:十个整数中可能有多个重复的数字,而且正是你要查找的,此时需要输出全部的位置,如果都查找了,没有找到的话就是没有找到. #include <stdio.h> int main(int argc,const char *argv[]) { int a[10],i,n; printf("请您输入10个整数:n

  • 在一个元素个数为N的数组里,找到升序排在N/5位置的元素的最优算法时间复杂度是----阿里巴巴2015实习生笔试题

    在一个元素个数为N的数组里,找到升序排在N/5位置的元素的最优算法时间复杂度是 正确答案: A   你的答案: B (错误) O(n) O(n log n) O(n (log n)2) O(n 3/2) 添加笔记 收藏 纠错 解析: BFPRT算法解决的问题十分经典,即从某n个元素的序列中选出第k大(第k小)的元素,通过巧妙的分 析,BFPRT可以保证在最坏情况下仍为线性时间复杂度.该算法的思想与快速排序思想相似,当然,为使得算法在最坏情况下,依然能达到o(n)的时间复杂 度,五位算法作者做了精

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值