日期:2014-05-20  浏览次数:20692 次

【C# 每日一题3】求第K大的数
C# code

原题如下:
Description

There are two sequences A and B with N (1<=N<=10000) elements each. All of the elements are positive integers. Given C=A*B, where '*' representing Cartesian product, c = a*b, where c belonging to C, a belonging to A and b belonging to B. Your job is to find the K'th largest element in C, where K begins with 1.

Input

Input file contains multiple test cases. The first line is the number of test cases. There are three lines in each test case. The first line of each case contains two integers N and K, then the second line represents elements in A and the following line represents elements in B. All integers are positive and no more than 10000. K may be more than 10000.

Output

For each case output the K'th largest number.

Sample Input

2
2 1
3 4
5 6
2 3
2 1
4 8
Sample Output

24
8


解释一下,定义数组A和数组B,里面都有n(1<=n<=10000)个元素,之后定义C数组,里面的元素c=a*b,a属于A,b属于B,之后求出C数组中第K大的数据!
输入:t代表有t组测试用例
输入N和K代表A和B数组中有N个元素,并且求C数组中的第K大的数据
之后输入A数组中的N个数据,和B数组中的N个数据!

例子(其中的一个测试用例):
1 ->一组测试用例
2 3 ->数组A B中分别有两个元素,求C中第3大的元素
2 1 ->数组A中的元素
4 8 ->数组B中的元素

之后C中的元素为 8 16 4 8,第三大的数据为 8

题记:
这个题暴力搜索是可以的,大家看看有没有更好的办法,暴力搜索的可以练一下自己的代码,贴一下!


------解决方案--------------------
算法题,帮顶学习了
------解决方案--------------------
以前做过,二分就可以了。n*log(n)的,如果用内插法的话,效率会更好一些。
------解决方案--------------------
这是以前写的一个,大概可以算100万的数据规模,用的是二分,如果有时间可以改个内插法的试试

C# code

using System;

namespace CSharpTest
{
    class Program
    {
        public static int[] A = new int[1000000], B = new int[1000000];
        public static Random Rnd = new Random(2010);//统一一个随机种子好验证

        public static void FillRandomValues(int[] arr)//随机填充
        {
            for (var i = 0; i < arr.Length; i++)
                arr[i] = Rnd.Next();
        }

        public static void Main()
        {
            FillRandomValues(A);
            FillRandomValues(B);
            //排序
            Array.Sort<int>(A);
            Array.Sort<int>(B);

            //根据输入的K输出结果
            while (true)
            {
                long k;
                if (long.TryParse(Console.ReadLine(), out k))
                {
                    if (k == 0) break;
                    Console.WriteLine(KthElement(k));
                }
            }
        }

        //求第K个元素
        static long KthElement(long k)
        {
            //该数肯定位于upper和lower之间
            long upper = (long)A[A.Length - 1] * B[B.Length - 1], lower = A[0] * B[0];
            return Solve(upper, lower, k);
        }

        //二分查找该值
        static long Solve(long upper, long lower, long count)
        {
            if (upper == lower) return upper;

            long mid = (upper + lower) >> 1;

            if (Counter(mid) >= count)
                return Solve(upper, mid + 1, count);

            if (Counter(mid - 1) < count)
                return Solve(mid - 1, lower, count);

            return mid;
        }

        //统计比指定value大的数有多少个
        static long Counter(long value)
        {
            int i = 0, j = B.Length - 1;
            long count = 0;

            while (i < A.Length && j >= 0)
            {
                if ((long)A[i] * (long)B[j] > value)
                {
                    count += A.Length - i;
                    j--;
                }
                else
                    i++;
            }

            return count;
        }
    }
}

------解决方案--------------------
用堆排序求第K大数据比较好
------解决方案--------------------