zoukankan      html  css  js  c++  java
  • 面试题:1~ n1 有n个数,是有序的,找出重复的那个数。

    话说这道题有多种解法:
    第一种:数学解法
    举例
    1 2 3 4 = 10
    1 2 3 3 = 9
    那么我们可以计算出  4 - (10-9) = 3 则3是重复的。
    所以我们只要得到 1~ n-1 的和,就可以用高斯公式算出这个结果,但是前提是要知道和,那么遍历数组时间复杂度是O(n)。
    如果这个数列不是有序的,这个方法依然通用。

    第二种:折半查找法
    由于这个数列是有序的,所以用折半查找法是再合适不过了。
    array[n/2 -1] == n/2 ?不满足则往前找,满足往后找。时间复杂度是O(logn)

    第三种:折X份查找法 
    折多少份?这个很有趣,其中有一道面试题和这个题目类似。

    【题目】 话说有2个杯子,100层楼。 杯子可以在某层摔碎,用最少次测试出哪层(最底层)能摔碎杯子? 

    这个摔杯子可以从第一层一层层摔,最多100次,也可以2层2层摔,最多50次,也可以3层3层摔,最多33次。还能更快吗?
    中午吃饭的时候某同事说可以用二分法的反向思维来做 比如 2->4->8->16->32->64->100  这个跨度越来越大,最多也要30来次。虽然这个方法不是想要的结果,但给了我们一个启示就是 我们可以找一个比较合适的度。 比如直接找某楼摔,不行再回来,行了就可以省去很多层楼,这个思想很重要。

    如果我们累加呢?   1 3 6 10 15 21 28 36 45 55 66 78  91 100 这样最多是12+12=24次还能更快吗?
    反向过来递减?那么次数最多的则是第一次的那层! 14 27 39 50 60 69 77 84 90 95 99 ... omg 这。。。 还能更快吗?
    x+x*x >= 2n 那么,最优的次数是x 。
    找重复的那个数和摔杯子不完全一样,因为我们不是2个杯子只有2次摔碎的机会。我们有N次机会。 所以 我们如果测出14摔碎,可以直接 5 9 13-> 3 -> 1 这么摔。


            static void getRepeater(int s, int x, int n, int[] array)
            {
                
    if (x == 1)
                {
                    Console.Write(array[s 
    - 1]);
                    Console.Read();
                    
    return;
                }
                
    if (array[s - 1!= s)
                {
                    n 
    = x;
                    x 
    = getX(x);
                    s 
    -= x;
                    getRepeater(s, x, n, array);
                }
                
    else
                {
                    x
    --;
                    getRepeater(s 
    + x, x, n - x, array);
                }
            }
            
    static int getX(int n)
            {
                var x 
    = 1;
                
    while (x + x * x < 2 * n)
                {
                    x
    ++;
                }
                
    return x;
            }
            
    static void Main(string[] args)
            {
                
    int[] array = { 1234567891011,11121314151617181920 };
                
    int n = array.Length;
                
    int x = getX(n);
                
    int s = x;
                getRepeater(s, x, n, array);
            }

  • 相关阅读:
    LeetCode对撞指针汇总
    167. Two Sum II
    215. Kth Largest Element in an Array
    2018Action Recognition from Skeleton Data via Analogical Generalization over Qualitative Representations
    题解 Educational Codeforces Round 84 (Rated for Div. 2) (CF1327)
    题解 JZPKIL
    题解 八省联考2018 / 九省联考2018
    题解 六省联考2017
    题解 Codeforces Round #621 (Div. 1 + Div. 2) (CF1307)
    题解Codeforces Round #620 (Div. 2)
  • 原文地址:https://www.cnblogs.com/mad/p/1597642.html
Copyright © 2011-2022 走看看