算法之 — 求二维数组最大n个数 - litonghui/TechBlog GitHub Wiki

最近看到某公司一道算法面试题,题目是一个m*n的二维数组matrix中,找到最大k个数。

分析题目,考查知识点是对多维数据的查找和排序,不要被二维数组这个概念给带偏了,对于二维数组我们一贯的认知就是一位数组简单分割。需要注意的是二维数组 matrix 在使用前需要对matrix.length 和 matrix[0].length 判断。

解法一:

对数组降维,new 一个 m*n 的一维数组matrix_s ,存储二维数组matrix 的所有数值,通过对一维数组降序排序(快排,堆排等),取前k个数,即所需要。时间复杂度和空间复杂度相比而言比较大,对于较大的二维数组,不是最优解法。

解法二:

采取DP算法思想,new 一个 k的 一维数组matrix_s ,遍历二维数组matrix,给一维数组matrix_s赋值,直到matrix_s 数组被赋满值,此时一维数组matrix_s 进行降序排序(快排,堆排等),至于后面的二维数组 m*n-k个数插入matrix_s数组中 ,插入时只需判断,matrix[i][j] > matrix_s[k-1]才允许插入,当然保证matrix_s 数组降序,采用尾部遍历,插入适当位置。

代码分析:

public int[] findMaxArray(int [][] matrix,int k) {
    if (matrix.length == 0 || k == 0)
        return new int[0];
    int[] arr = new int[k];
    int x = 0;
    for (int i = 0; i < matrix.length; i++)
        for (int j = 0; j < matrix[i].length; j++) {
            if (x < k) {
                arr[x] = matrix[i][j];
                x++;
                if (x == k) {
                    sortArr(arr);
                }
            } else {
                insertSort(arr,matrix[i][j]);
            }
        }
    return arr;
}

快速排序对一维数组,保证降序

public int[] sortArr(int[] arr) {
    quickSort(arr, 0, arr.length - 1);
    return arr;
}
public void quickSort(int[] arr,int left,int right) {
    if (left >= right)
        return;
    int low = left, heigth = right;
    int k = arr[left];
    while (left < right) {
        while (left < right && arr[right] < k)
            right--;
        arr[left++] = arr[right];
        while (left < right && arr[left] > k)
            left++;
        arr[right--] = arr[left];
    }
    arr[left] = k;
    quickSort(arr, low, left - 1);
    quickSort(arr, right + 1, heigth);
}

倒叙插入降序数组,采用动态规划方式,选取始终大于当前数组最小的元素插入。

public void insertSort(int []arr,int num) {
    if (arr[arr.length - 1] > num)
        return;
    int i;
    for (i = arr.length - 1; i > 0; i--) {
        if (arr[i - 1] < num) {
            arr[i] = arr[i - 1];
        } else {
            break;
        }
    }
    arr[i] = num;
}

测试一下设计是否正确(Android log 方式):

    int[][] matrix = {{4, 12, 13}, {1, 45, 7}, {8, 9, 12}, {0, 6, 11}};
    int [] max = findMaxArray(matrix,8);
    StringBuilder builder = new StringBuilder();
    for (int m:max){
        builder.append(m).append(",");
    }
    Log.v("lth","max:"+builder);