JAVA算法-数组

作者: 湘北南 | 来源:发表于2018-10-02 10:10 被阅读15次

数组是一种很常见的数据结构,知道索引,可以快速定位到具体元素,然而,数组中添加和删除元素会很慢,下面讲讲关于数组的一些算法题。

1. 一个二维数组,每一行从左到右递增,每一列从上到下递增, 输入一个二维数组和一个整数,判断数组中是否含有整数:

例如:二维数组如下,输入数字是12,则函数应该返回true。
1 4 8 9 10
2 5 9 11 12
5 7 10 12 14

解题思路:

我们知道这个二维数组横向是递增的,竖向也是递增的,我们拿输入的数字num = 12(假设输入的num是12),和数组的右上角元素a[0][n]比较,会出现三种情况,并对这三种情况做具体分析:

1) num > a[0][n] ,则num一定不在第一行,因此我们需要在第2、3...行来找;

2) num < a[0][n] ,则num一定不在第n列,因此我们需要在第n-1、n-2...列来找;

3) num = a[0][n] ,则返回true。

算法实现:

public static boolean findNumInArray(int[][] array, int num) {
        if (array == null) return false;
        int n = array[0].length - 1;
        int row = array.length;
        int m = 0;
        while (n >= 0 && m <= row - 1) {
            if (array[m][n] < num) {
                m++;
            } else if (array[m][n] == num) {
                return true;
            } else {
                n--;
            }
        }
        return false;
    }

时间复杂度:O(m+n),空间复杂度O(1)。

2. 给定一个元素为1到N(N>=1)的正整型数组,找到1到N缺少的数字:

例如:假设N是5,数组元素是2,3,4,5,则需要找到缺少的数字1。

解题思路:

如果这个正整型的数组只缺少一个数字,且没有重复的数字,则我们可以这么做,分以下两步:

1)求1到N的和为total;

2)遍历数组,用total减去数组的每个元素,最后得到的值就是这个缺少的数字。

算法实现:

/**
     * 如果返回值是-1,则代表没有找到缺少的元素
     * @param array
     * @param N
     * @return
     */
    public static int findLeakNumInArray(int[] array, int N){
        int num = -1;
        if(array == null || N <= 0){
            return num;
        }
        if(array.length > 0){
            //求1到N的和
            int total = (1+ N) * N /2;
            for(int i = 0 ; i < array.length ; i++){
                //用和减去数组的元素,最后得到的就是缺少的元素
                total -= array[i];
            }
            num = total;
        }
        return num;
    }

时间复杂度:O(n),空间复杂度O(1)。

延伸:假设1到N的正整型数组,缺少多个数字,且包含重复的数字,我们该怎么找到缺少的数字呢?

例如:假设N是5,数组元素是4,3,4,3,则需要找到缺少的数字1,2,5。

解题思路:

1)我们可以给new一个N+1的tmp数组,索引从1开始,到N结束;

2)遍历正整型数组array,并将元素array[i]作为tmp数组的索引,找到一个元素,tmp[array[i]]的值加1;

3)从1开始遍历tmp数组,找出值为0的对应的索引输出,即找到了缺失的数字。

算法实现:

public static void findLeakNumInArray1(int[] array, int N){
        if(array == null || N <= 0){
            return;
        }
        if(array.length > 0){
            int[] temp = new int[N +1];
            for(int i = 0 ; i < array.length ; i++){
                temp[array[i]] += 1;
            }

            System.out.print("leak num:");
            for(int i = 1 ; i < temp.length; i++){
                if(temp[i] == 0){
                    System.out.print( i + " ");
                }

            }
            System.out.print("\n");
        }
    }

时间复杂度:O(n),空间复杂度O(n)。

3. 在给定的整数数组中,找出两个数相加的和等于给定的数字。

例如:给定的数组int[] a = {3,4,2,6,8},target数字是5,则找到两个数相加和等于5的数字是3,2。

解题思路:

1)我们可以声明一个map,用来存储数组的元素和对应的索引;

2)遍历数组,用给定的数target减去a[i] ,判断(target-a[i])在map是否存在:

不存在,则将a[i]和i添加到map中;

存在,则取出(target-a[i])的索引和i,并返回对应的数字。

算法实现:

public static int[] findTwoNum(int[] array, int target){
        if(array == null || array.length <=0){
            return  null;
        }

        HashMap<Integer, Integer> recordMap = new HashMap<>();
        for(int i = 0 ; i < array.length; i++){
            if(recordMap.containsKey(target- array[i])){
                int indexOne = recordMap.get(target- array[i]);
                int indexTwo = i;
                return new int[]{array[indexOne], array[indexTwo]};
            }else{
                recordMap.put(array[i], i);
            }

        }
        return  null;

    }

时间复杂度:O(n),空间复杂度O(n)。

4. 在给定的整数数组中,连续的几个数是重复的,请删除数组重复的数。

例如:给定数组int[] a = {3,3,3,4,2,2,6,5,5,8,9,10,10},删除重复的数后,数组变成int[] a = {3,4,2,6,5,8,9,10}

解题思路:

我们使用两个指针,分别是慢指针cur,快指针pre,它们的初始值都是0,然后遍历数组,分以下两种情况讨论:

1)如果a[cur] != a[pre],则cur++,同时赋值:a[cur] = a[pre];

2)反之a[cur] = a[pre],说明当前元素跟快指针遍历的元素是重复的,则继续往后遍历,找到不等重复步骤1,如果相等重复步骤2。

算法实现:

public static  void removeDupData(int[] data){
        if(data == null || data.length <=0 ){
            return;
        }
        int cur = 0;
        for(int pre = 0; pre < data.length; pre++){
            if(data[pre] != data[cur]){
                cur++;
                data[cur] = data[pre];
            }
        }

        int len = cur < data.length ? cur +1: data.length;

        System.out.print("remove duplicate data:");

        for(int i = 0; i < len; i ++){
            System.out.print(data[i] + " ");

        }
        System.out.print("\n");

    }

时间复杂度:O(n)。

4. 正整数反转:给定一个正整数123456,移动数组末位的N个元素,如N = 2,则输出56,1234;N = 4,则输出3456,12。

解题思路:

1)假设原始数组的长度为length,我们可以声明一个数组,可以先装载后面要移动的N个数字,再把原始数组前面(length - N)个数字向后移动N位,最后把存储到新数组的N个数字copy到原数数组的前N位。

注意事项:

移动N个元素跟移动 N%length 元素是一样的,如N = 7,则上面正整数移动7位变成 6,12345,跟 N % length = 7%6 = 1效果是一样的。

因此,我们新声明的数组的长度应该是 N%Length。

2)上面的解题思路会新开辟一个数组,我们想想有没有其它不用开辟内存空间的解法了。其实,这题跟字符串的反转是同一个思路:

例如给定一个字符串abcdef,反转字符串最后两位,则变成了ef,abcd。

我们解该题一般分为两部分,先反转整个字符串,再反转隔开后的两个字符串:

abcdef -> fedcba

fe dcba ->ef abcd

算法实现:

public static void rotateArray(int[] data, int times) {
        if (data == null || data.length <= 0 || times <=0) {
            return;
        }
        int rotateNum = times % data.length;

        //global inversion
        for (int start = 0, end = data.length -1; start <= end; start ++, end--){
            swap(data, start,end);

        }
        //local inversion
        for (int start = 0, end = rotateNum -1; start <= end; start ++, end--){
            swap(data, start,end);
        }
        //local inversion
        for (int start = rotateNum, end = data.length -1; start <= end; start ++, end--){
            swap(data, start,end);
        }


        for(Integer item: data){
            System.out.print(item);

        }
        System.out.print("\n");

    }


    public static void swap(int[] data, int start , int end){
        int tmp = data[start];
        data[start] = data[end];
        data[end] = tmp;

    }

测试代码:

public static void main(String[] args) {
      
        int[] data = {1,2,3,4,5,6};

        rotateArray(data, 4);

        System.exit(0);

    }

时间复杂度:O(n)。

相关文章

  • Hash算法

    数据结构与算法分析:大纲数据结构:数组算法:hash算法算法:排序算法Java实现 1 Hash算法? 将任意长度...

  • JAVA算法-数组

    数组是一种很常见的数据结构,知道索引,可以快速定位到具体元素,然而,数组中添加和删除元素会很慢,下面讲讲关于数组的...

  • 2019-07-19数据结构

    计算机本来没有算法先有编码,后有数据结构,然后有可算法 基础数据结构 数组 java 内置 顺序存储数组的缺点,...

  • 数组 - Array

    新建数组 数组的下标是从0开始 Java中,访问数组注意是否越界 打擂台算法Example:找出数组中前两大的数 ...

  • Java数组算法(实用)

    数组知识导图 数组拷贝:public class ShuZuTest { }

  • Java算法之数组

    Java数组的基础知识 为什么要引入数组? 需求:现在需要统计某公司员工的工资情况,例如计算平均工资、找到最高工资...

  • Java(数组与算法)

    之前的Java基础的学习耽搁了好久,最近也没啥事做,继续之前的学习进度吧。这次内容主要是Java数组的知识点,和冒...

  • Java数组排序算法

    冒泡排序(BubbleSort) 冒泡排序的基本思想是对比相邻的元素值,如果满足条件就交换元素,把较小的元素移动到...

  • 最大子数组

    最大字数组问题一种java实现,理论部分参见算法导论分治策略

  • JavaSE进阶-03-算法

    算法实际上在Java中不需要精通,因为Java已经封装好了。例如Java中提供了一个数组工具类:java.util...

网友评论

    本文标题:JAVA算法-数组

    本文链接:https://www.haomeiwen.com/subject/oodpoftx.html