您的位置:首页 > 其它

360校招笔试题

2017-08-29 20:17 204 查看
上周末,一个读研的同学做360的笔试题,把没有做出来的题分享给我,我看后也是一脸懵逼,过了2天才想出来。

给一个数组,计算每个数字之前有几个比它大的

比如输入 4 5 1 2 3 输出0 0 2 2 0

数组长度1-200 000,数值大小1-200 000

要求运行时间不能超过4秒 (C语言是1秒) ,内存限制6.5G

就算按CPU一秒能够运行50亿次来算,200 000 * 200 000 / 500 000 000 = 80秒,显然O(N^2)的做法是行不通的,这时就想到了对数,会不会是空间换时间呢。当时就想到借助一个数据结构,查找、插入的时间复杂度都不超过logN,而且查找到对应位置之后还能计算下标,得到该元素后边还有多少个元素。可是实际场景是1小时做3道算法题,这只是其中一道,平均一道题只有20分钟,再出去读上百字的题目理清题意,也就10分钟出头,写什么数据结构能够这么快写完。所以应该也不是这个思路,虽然确实能做。苦思冥想2天,终于想到了一个相对不错的办法

思路:归并排序升序,当把一个较小的数放到前面时,记录移动的位数

/**

 * 4 5 1 2 3

 * 0 0 2 2 0

 * @author txy

 *

 */

public class Test360 {

    public static int[] countArr = null;

    public static void sort(int[] nums){

        int[] temp = new int[nums.length];

        for(int i=0;i<nums.length;i++) {

            temp[i] = nums[i];

        }

        countArr = new int[getMax(nums)+1];

        sort(temp,0,temp.length-1);

    }

    private static int getMax(int[] nums) {

        int max = Integer.MIN_VALUE;

        for(int i:nums) {

            max = Math.max(max, i);

        }

        return max;

    }

    private static void sort(int[] nums, int start,int end) {

        if(start<end) {

            int mid = (start+end)>>1;

            sort(nums,start,mid);

            sort(nums,mid+1,end);

            merge(nums,start,mid,end);

        }

    }

    private static void merge(int[] nums, int start, int mid, int end) {

        int len1 = mid-start+1;

        int len2 = end-mid;

        int[] left = new int[len1];

        int[] right = new int[len2];

        int i,j,k;

        for(i=0;i<len1;i++) {

            left[i]=nums[start+i];

        }

        for(j=0;j<len2;j++) {

            right[j]=nums[mid+1+j];

        }

        i=0;j=0;

        for(k=start;k<end;k++) {

            if(i==len1 || j==len2) {

                break;

            }

            if(left[i]<=right[j]) {

                nums[k]=left[i++];

            }else {

                countArr[right[j]]+=(left.length-i);

                nums[k]=right[j++];

            }

        }

        while(i!=len1) {

            nums[k++] = left[i++];

        }

        while(j!=len2) {

            nums[k++] = right[j++];

        }

    }

    

    public static void main(String[] args) {

        int[] nums = new int[]{10, 4, 6, 3};

        sort(nums);

        for(int i:nums) {

            System.out.print(countArr[i]+" ");

        }

        

    }

}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  笔试题 算法