龙空技术网

阿里面试算法题(一)

技术王老五 59

前言:

现在朋友们对“阿里算法题没做出来能过吗”可能比较着重,我们都想要学习一些“阿里算法题没做出来能过吗”的相关文章。那么小编也在网上搜集了一些对于“阿里算法题没做出来能过吗””的相关知识,希望我们能喜欢,同学们一起来学习一下吧!

长度为N的数组arr,一定可以组成N^2个数值对

例如:arr = [3, 1, 2],

数值对有(3, 3)(3, 1)(3, 2)(1, 3)(1, 1)(1, 2)(2, 3)(2, 1)(2, 2),也就是任意两个数都有数值对,而且自己和自己也算数值对

数值对的排序规则,第一维数据从小到大,第一维数据一样的,第二维数据也从小到大

上面的数值对排序结果为:(1, 1)(1, 2)(1, 3)(2, 1)(2, 2)(2, 3)(3, 1)(3, 2)(3, 3)

给定一个数组arr,和整数k,返回第k小的数值对

what?就这么so easy的题。不就是列出所有的组合,然后比较对这些组合进行排序吗,这不是轻轻松松搞定面试官?搞定全宇宙吗?来让他们见识一下真正的技术吧。。。。

Talk is cheap. Show me the code.于是乎风骚的代码正式上线,

package com.edward.demo; import java.util.Arrays;import java.util.Comparator; //数值对public class Calculate {    public static  class PairArr{        public int first;        public int second;         public PairArr(int first, int second) {            this.first = first;            this.second = second;        }    }     public static class PairArrCompare implements Comparator<PairArr>{        @Override        public int compare(PairArr o1, PairArr o2) {            return o1.first != o2.first ? o1.first - o2.first : o1.second - o2.second;        }    }     public static int[] findKMinPair(int[] resources, int k){        int length = resources.length;        if( k > length * length){            return null;        }        PairArr[] pairArrs = new PairArr[length * length];        int index = 0;        for (int i = 0; i < length; i++) {            for (int j = 0; j < length; j++) {                pairArrs[index ++] = new PairArr(resources[i],resources[j]);            }        }        Arrays.sort(pairArrs,new PairArrCompare());        return new int[]{pairArrs[k - 1].first,pairArrs[k-1].second};    }        public static void main(String[] args) {        int[] resources = {1, 1, 2, 2, 2, 3,3};        int k = 21;        System.out.println(Arrays.toString(findKMinPair(resources,k)));    } }

区区几十行代码速度解决战斗,运行的demo也很丝滑,没有一点犹豫的就执行出来了,这精简而又通俗易懂的程度,往低了说也得99吧!!!信心慢慢的提交了答卷。面试官的反应

上面代码的复杂度:面试官会给你一个O(N^2log(N^2))

方法二:

我们再来分析一下整体的数组:例如{1, 2, 3},以下是所有的情况罗列

再举个例子{1, 1, 2, 2, 2, 3, 3},罗列所有的组合:

第一个数字是1与数组{1, 1, 2, 2, 2, 3, 3}匹配,获取所有的数字对是【1,数组所有的数字】

第二个数字是1与数组{1, 1, 2, 2, 2, 3, 3}匹配,获取所有的数字对是【1,数组所有的数字】.......

所以我们可以很轻松的获取到数值对的第一位数字:arr[(K -1 )/数组的长度]

第二位数字怎么获取呢????

还是arr = {1, 1, 2, 2, 2, 3, 3}这个数组,如果去第21小的数字对,我们可以轻松的获取到第一位数字:arr[(21 -1)/ 7] = arr[2] = 2 ,第一位是2

所有的数值对是从小大排列,arr有3个数字2,那么就会有 {2,2,2} 分别于{1, 1, 2, 2, 2, 3, 3}组成的组合,那么第二位的数字我们就呼之欲出了,arr[ (21 - 小于2数字的个数 * 7 - 1) / 3] = arr [( 21 - 2 * 7 - 1) /3]=arr[2] = 2;最后的结果就是 {arr[2],arr[2]} ={2,2}

show me the code

public static int[] findKMinPair2(int[] resources, int k){        int length = resources.length;        if( k > length * length){            return null;        }        Arrays.sort(resources);        //找出第一位数字        int firstNum = resources[(k - 1)/ length];         //小于firstNum的个数        int lessFirstNumSize = 0;        //找出等于firstNum的个数        int firstNumSize = 0;        for (int i = 0; i < length && resources[i] <= firstNum; i++) {            if(resources[i] < firstNum){                lessFirstNumSize++;            }else {                firstNumSize++;            }        }        int restK = k - (lessFirstNumSize * length);        return new int[]{firstNum,resources[(restK - 1) / firstNumSize]};    }

搞定,骚年你是不是感觉到这已经结束了???no no no, 骚年 too young too simple,你还是不太了解面试官

方法二天然的需要排序,如果是无需呢?这个问题就换成了,在一个无序的数组中获取到第K小的数据,是不是有点熟悉,这就是TOP-K问题,,大名鼎鼎的BFPTR算法(也叫中位数的中位数算法),该算法可以从一堆无序数字中拿出第k小的数字,而且,而且最神奇的是!!!该算法在最坏情况下的时间复杂度竟然只有O(N)

public static int[] findKMinPair2(int[] resources, int k){        int length = resources.length;        if( k > length * length){            return null;        }        Arrays.sort(resources);        //找出第一位数字        int firstNum = bfptr(resources,0,length - 1,(k -1 )/ length + 1);         //小于firstNum的个数        int lessFirstNumSize = 0;        //找出等于firstNum的个数        int firstNumSize = 0;        for (int i = 0; i < length && resources[i] <= firstNum; i++) {            if(resources[i] < firstNum){                lessFirstNumSize++;            }else {                firstNumSize++;            }        }        int restK = k - (lessFirstNumSize * length);        int second = bfptr(resources,0,length - 1,(restK - 1) / firstNumSize + 1);         return new int[]{firstNum,second};    }     public static void main(String[] args) {        int[] resources = {1, 1, 2, 2, 2, 3, 3};        int k = 21;        System.out.println(Arrays.toString(findKMinPair2(resources,k)));    }     public static int findMid(int[] arr,int l,int r){        if (l == r) return arr[l];        int i;        int n = 0;        for(i = l; i < r - 5; i += 5){            insertSort(arr, i, i + 4);            n = i - l;            swap(arr,l + n / 5, i + 2);        }         //处理剩余元素        int num = r - i + 1;        if(num > 0){            insertSort(arr, i, i + num - 1);            n = i - l;            swap(arr,l + n / 5, i + num / 2);        }        n /= 5;        if(n == l) return arr[l];        return findMid(arr, l, l + n);    }     public static int findMidIndex(int[] arr,int l,int r,int num){        for (int i = l; i <= r; i++) {            if (arr[i] == num) return i;        }        return -1;    }     public static int Partition(int[] arr, int l, int r, int p){        swap(arr,p, l);        int i = l;        int j = r;        int pivot = arr[l];        while(i < j){            while(arr[j] >= pivot && i < j)                j--;            arr[i] = arr[j];            while(arr[i] <= pivot && i < j)                i++;            arr[j] = arr[i];        }        arr[i] = pivot;        return i;    }     //插入排序    public static void insertSort(int[] arr,int l,int r){        for (int i = l + 1; i <= r; i++) {            if (arr[i - 1] > arr[i]) {                int t = arr[i];                int j = i;                while (j > l && arr[j - 1] > t) {                    arr[j] = arr[j - 1];                    j--;                }                arr[j] = t;            }        }    }    //数组元素交换    public static void swap(int[] arr,int i,int j){        int temp = arr[i];        arr[i] = arr[j];        arr[j] = temp;    }     public static int bfptr(int[] arr,int l,int r,int k){        int num = findMid(arr, l, r);    //寻找中位数的中位数        int p =  findMidIndex(arr, l, r, num); //找到中位数的中位数对应的index        int i = Partition(arr, l, r, p);         int m = i - l + 1;        if(m == k) return arr[i];        if(m > k)  return bfptr(arr, l, i - 1, k);        return bfptr(arr, i + 1, r, k - m);    }

骚年 想知道更多的套路吗?欢迎关注:叮铛的公众号,套路三联。。。。。。

欢迎关注作者公众号交流:技术小叮铛!!!!技术小叮铛!!!!!

私信+留言+关注+转发可以可以免费领取一份大厂面试题

标签: #阿里算法题没做出来能过吗