【数据结构】数组

1,概念

数组一旦定义,其维数和维界就不再改变。
因此除了结构的初始化和销毁之外,数组只有存取元素和修改元素值的操作。

1)java中定义

float f[][] = new float[6][6];
float []f[] = new float[6][6];
float [][]f = new float[6][6];
float [][]f = new float[6][];

程序设计语言中,数组元素在内存中是一个接着一个线性存放的,通过第一个元素就能访问随后的元素,这样的数组称之为“真数组”。
实现了真数组为Java语言健壮性的特点之一。

2,应用

1)哈希表

把数组的下标设为哈希表的键值(key),而把数组中每一个数字设为哈希表的值(value),有了这样的哈希表,就可以O(1)实现查找。从而快速高效的解决很多问题。

2)二维数组的查找

在一个二维数组中,每一行都按照从左到右递增的顺序排序,每一列都按照从上到下递增的顺序排序。请完成一个函数,输入这样的一个二维数组和一个整数,判断数组中是否含有该整数。

如下,二维数组每行每列递增排序,查找一个数字,找到返回true,否则false
1    2    8    9
2    4    9    12
4    7    10   13
6    8    11   15

解决方案:
方案一:二分查找。
方案二:(推荐)
对于目标数字num_target,首先选取数组右上角的数字right_num,
如果right_num == num_target ,返回true;
如果right_num > num_target ,剔除所在列;
如果right_num < num_target ,剔除所在行;
如果查找范围为空,返回false;

public boolean find(int[][] array, int target) {
        if (array == null) {
            return false;
        }
        int row = 0;
        int column = array[0].length - 1;
        while (row < array.length && column >= 0) {
            if (array[row][column] == target) {
                return true;
            }
            if (array[row][column] > target) {
                column--;
            } else {
                row++;
            }
        }
        return false;
    }

3)旋转数组的最小数字

把一个数组最开始的若干个元素搬到数组的末尾,我们称之为数组的旋转。 输入一个非递减排序的数组的一
个旋转,输出旋转数组的最小元素。 例如数组{3,4,5,1,2}为{1,2,3,4,5}的一个旋转,该数组的最小值为1。
NOTE:给出的所有元素都大于0,若数组大小为0,请返回0

思路:利用二分法,找到中间的数,然后和最左边的值进行比较,若大于最左边的数,则最左边从mid开始,
若小于最右边值,则最右边从mid开始。若左中右三值相等,则取mid前后值中较小的数。

    public int minNumberInRotateArray(int [] array) {
        if (array == null || array.length == 0)
            return 0;
        int left = 0;
        int right = array.length - 1;
        int mid = 0;
        while (array[left] >= array[right]) {
            if(right - left <= 1) {
                mid = right;
                break;
            }
            mid = (left + right)/2;
            if (array[left] == array[mid] && array[mid] == array[right]) {
                if (array[left+1] != array[right-1]) {
                    mid = array[left+1] < array[right-1] ? left+1:right-1;
                } else {
                    left++;
                    right--;
                }
            } else {
                if (array[left] <= array[mid]) {
                    left = mid;
                } else {
                    right = mid;
                }
            }
        }
        return array[mid];
    }

注意:对于二分查找,如果两个数相同,并且他们中间的数也相同,那么就无法识别出要查找的数字的具体位置,如:{0,1,1,1,1}的旋转:{1,0,1,1,1}。只能用顺序查找方式来实现。

4)顺时针打印矩阵

输入一个矩阵,按照从外向里以顺时针的顺序依次打印出每一个数字,例如,如果输入如下矩阵,依次打印出数字1,2,3,4,8,12,16,15,14,13,9,5,6,7,11,10。

1  2  3  4
5  6  7  8 
9  10 11 12 
13 14 15 16 

思路:
每次打印一圈,循环打印。每圈终止条件是(start,start)(第一圈中止为(1,1),第二圈为(2,2)。
最后一圈判断,即循环条件为matrix[0].length > start * 2 && matrix.length > start * 2,在中间。

 public ArrayList<Integer> printMatrix(int[][] matrix) {
        ArrayList<Integer> list = new ArrayList<>();
        if (matrix == null)
            return list;
        int start = 0;
        while (matrix[0].length > start * 2 && matrix.length > start * 2) {
            printOneCircle(matrix, start, list);
            start++;
        }
        return list;
    }

    private void printOneCircle(int[][] matrix, int start, ArrayList<Integer> list) {
        int endX = matrix[0].length - 1 - start; // 列
        int endY = matrix.length - 1 - start; // 行
        // 从左往右 (列号大于行号)
        for (int i = start; i <= endX; i++)
            list.add(matrix[start][i]);
        // 从上往下(行号大于列号)
        if (start < endY) {
            for (int i = start + 1; i <= endY; i++)
                list.add(matrix[i][endX]);
        }
        // 从右往左(判断是否会重复打印)
        if (start < endX && start < endY) {
            for (int i = endX - 1; i >= start; i--)
                list.add(matrix[endY][i]);
        }
        // 从下往上(判断是否会重复打印)
        if (start < endX && start < endY - 1) {
            for (int i = endY - 1; i >= start + 1; i--)
                list.add(matrix[i][start]);
        }
    }

猜你喜欢

转载自blog.csdn.net/SunshineTan/article/details/80976994