• leetcode算法-最长和谐子序列


    这两天正在忙实习找工作,晚上就抽时间写写算法,放松一下子

    一、题目

    和谐数组是指一个数组里元素的最大值和最小值之间的差别正好是1。

    现在,给定一个整数数组,你需要在所有可能的子序列中找到最长的和谐子序列的长度。

    示例 1:

    输入: [1,3,2,2,5,2,3,7]
    输出: 5
    原因: 最长的和谐数组是:[3,2,2,2,3].
    说明: 输入的数组长度最大不超过20,000.

    二、解题思路

    此题的意思,无非就是在在排好序的数组中,找到最大值和最小值相差一的,且距离最远的两个元素,加一即可

    所以,首先对数组进行排序,排序算法本人了解比较快的又相对简单的还是快速排序,所以就用快速排序先进行排序,之后采用双层循环,第一层从左到右遍历数组中的元素,第二层从右到左遍历元素,直到找出比外层循环大一的元素(没有就循环完),此时计算长度,与原来长度对比,选出最大的,跳出本次循环,直到结束。

    注意:二层循环不可以从左向右循环,原因是如果最大的数有好几个相同的,就会处理着很麻烦。

    三、代码:

        public static void main(String[] args) {
            int[] array = new int[] { 1, 3, 2, 2, 5, 2, 3, 7 };
            System.out.println(getHarmoniousArrayLength(array));
        }
    
        public static int getHarmoniousArrayLength(int[] array) {
            // 首先对数组进行有序化
            quickSort(array, 0, array.length - 1);
            // 存储最大数量
            int max = 0;
            for (int i = 0; i < array.length - 1; i++) {
                for (int j = array.length - 1; j > i; j--) {
                    // 判断是否符合条件
                    if (array[i] + 1 == array[j]) {
                        // 计算长度
                        int result = j - i + 1;
                        // 选出长度最大的差值
                        if (result > max) {
                            max = result;
                            break;
                        }
                    }
                }
            }
            return max;
    
        }
    
        // 快速排序
        public static void quickSort(int[] array, int low, int high) {
            // 最小数组
            if (low < high) {
                int i = low;
                int j = high;
                int middle = array[low];
                // 进行判断,并且互换
                while (i < j) {
                    // 寻找出左边的不合适元素
                    while (i < j && array[j] >= middle) {
                        j--;
                    }
                    // 寻找出右边的不合适元素
                    while (i < j && array[i] <= middle) {
                        i++;
                    }
                    if (i < j) {
                        int temp = array[i];
                        array[i] = array[j];
                        array[j] = temp;
                    }
                }
                // 将基准和最后指针位置的数进行互换
                array[low] = array[j];
                array[j] = middle;
                // 将基准数左边和右边进行同样的操作
                quickSort(array, low, j - 1);
                quickSort(array, j + 1, high);
            }
        }

    效率截图:

     

    四、优化算法

    第二天重新看题,发现内循环如果倒叙虽然方便了不少,但是对于较长的数组说,遍历的无用数据过多,造成时间的大量浪费,采用正序遍历,当数字不为第一个数或者不为第一个数加一时,就跳出循环,判断跳出循环位置的前一个数是否时循环外层数组加一,如果按正常走完,没跳出循环,则要进行相同的判断。

    代码如下:

        // 首先对数组进行有序化
            quickSort(array, 0, array.length - 1);
            // 存储最大数量
            int max = 0;
            for (int i = 0; i < array.length - 1; i++) {
                int j = 0;
                for (j = i+1; j < array.length; j++) {
                    if(j == array.length - 1) {
                        
                    }
                    // 判断是否符合条件
                    if (array[i] != array[j] && array[i]+1 != array[j]) {
                        if(array[i] + 1 == array[j - 1]) {
                            // 计算长度
                            int sum = j - i; 
                            if(max < sum) {
                                max = sum;
                            }
                        }
                        break;
                    }        
                }
                // 统一处理
                if(array[i] + 1 == array[j - 1]) {
                    // 计算长度
                    int sum = j - i; 
                    if(max < sum) {
                        max = sum;
                    }
                }
            }
            return max;
    
        }
    
        // 快速排序
        public static void quickSort(int[] array, int low, int high) {
            // 最小数组
            if (low < high) {
                int i = low;
                int j = high;
                int middle = array[low];
                // 进行判断,并且互换
                while (i < j) {
                    // 寻找出左边的不合适元素
                    while (i < j && array[j] >= middle) {
                        j--;
                    }
                    // 寻找出右边的不合适元素
                    while (i < j && array[i] <= middle) {
                        i++;
                    }
                    if (i < j) {
                        int temp = array[i];
                        array[i] = array[j];
                        array[j] = temp;
                    }
                }
                // 将基准和最后指针位置的数进行互换
                array[low] = array[j];
                array[j] = middle;
                // 将基准数左边和右边进行同样的操作
                quickSort(array, low, j - 1);
                quickSort(array, j + 1, high);
            }
        }

    效率截图:

     效率提升了30倍左右。。。。。。

  • 相关阅读:
    养生之《爱的供养》
    道家养生,与佛家养德
    个人的佛法·5·活着,与死去
    自我囚禁与安住于轮回
    个人的佛法·4·我是不是东西?
    个人的佛法·2
    我们都是生命的灯塔
    大O表示法是什么?
    uni-app商城项目(01)
    2059
  • 原文地址:https://www.cnblogs.com/mcjhcnblogs/p/13096111.html
Copyright © 2020-2023  润新知