zoukankan      html  css  js  c++  java
  • 算法------长度最小的子数组

    长度最小的子数组
    给定一个含有 n 个正整数的数组和一个正整数 s ,找出该数组中满足其和 ≥ s 的长度最小的连续子数组。如果不存在符合条件的连续子数组,返回 0。
    
    示例: 
    
    输入: s = 7, nums = [2,3,1,2,4,3]
    输出: 2
    解释: 子数组 [4,3] 是该条件下的长度最小的连续子数组。
    进阶:
    
    如果你已经完成了O(n) 时间复杂度的解法, 请尝试 O(n log n) 时间复杂度的解法。
    

    我的解答:

    第一版本:有问题的版本
    class Solution {
        public int minSubArrayLen(int s, int[] nums) {
    /*        第一版:   思路有问题  213
                    [12,28,83,4,25,26,25,2,25,25,25,12]*/
            if (nums == null || nums.length == 0) {
                return 0;
            }
    
            int maxNumber = 0;
            int maxNumIndex = 0;
            int total = 0;
            int length = nums.length;
            for (int i = 0; i < length; i++){
                if (nums[i] > maxNumber) {
                    maxNumber = nums[i];
                    maxNumIndex = i;
                }
                total += nums[i];
            }
    
            if (total < s){
                return  0;
            }else if (maxNumber >= s){
                return maxNumIndex;
            }
            int min = 0;
    
            total = 0;
            int lenghth1 = 0;
            // 从 maxIndex 往后遍历
            for (int number = maxNumIndex; number < length ; number++) {
                total += nums[number];
                lenghth1 ++;
                if (total >= s) {
                    min = lenghth1;
                    break;
                }
            }
            total = 0;
            int lenghth2 = 0;
            // 从 maxindex 向前遍历
            for (int number = maxNumIndex; number >=0 ; number--) {
                total += nums[number];
                lenghth2 ++;
                if (total >= s) {
                    min =min !=0 ? Math.min(min,lenghth2) : lenghth2;
                    break;
                }
            }
            int lenghth3 = 0;
            if (maxNumIndex != 0 && maxNumIndex != length -1) {
                lenghth3 = 1;
                // 从maxIndex 从中间往两边遍历
                for (int i = maxNumIndex-1 ,j= maxNumIndex+1; j >0 && j< length  && i < length && i>=0 ;i ++,j--) {
                    total += nums[i]+nums[j];
                    lenghth3 +=2;
                    if (total >= s) {
                        min =min !=0 ? Math.min(min,lenghth3) : lenghth3;
                        break;
                    }
                }
            }
            return min;
            }
            }
    

    当时我的想法是:找到最大的那个数,要找的和肯定是最大的数组成的子数组长度比较小。后来忘了,如果说,该数很大,但是周围都是1,也比不过其他比他小,但是周围都是同等大的数。比如:1,1,1,23,1,1,1,1,18,18,18.

    第二版:实在想不出来方法,就用循环遍历去做吧。

    class Solution {
        public int minSubArrayLen(int s, int[] nums) {
     if (nums == null || nums.length == 0) {
                return 0;
            }
    
            int maxNumber = 0;
            int total = 0;
            int length = nums.length;
            for (int i = 0; i < length; i++){
                if (nums[i] > maxNumber) {
                    maxNumber = nums[i];
                }
                total += nums[i];
            }
    
            if (total < s){
                return  0;
            }else if (maxNumber >= s){
                return 1;
            }
    
            int minCont = 0;
            for (int i = 0; i < length; i++) {
                total = 0 ;
                total += nums[i];
                for (int j = i+1;j < length;j++){
                    total += nums[j];
                    if (total >= s) {
                        minCont =minCont !=0 ? Math.min(j-i,minCont) :j-i;
                        break;
                    }
                }
            }
            return ++minCont;}
            }
    

    肯定有很多重复遍历。

    网上最快的方法:

    class Solution {
        public int minSubArrayLen(int s, int[] nums) {
            // copy from leetcode.com
            if (null == nums || nums.length == 0) { return 0; }
            int i = 0, j = 0;
            int sum = 0, minLen = Integer.MAX_VALUE;
            while (j < nums.length) {
                sum += nums[j++];
                if (sum < s) { continue; }
                while (sum >= s) {
                    sum -= nums[i];
                    i++;
                }
                minLen = Math.min(minLen, j - i + 1);
            }
            return (minLen == Integer.MAX_VALUE) ? 0 : minLen;
    
        }
    }
    

    总结

    1.感觉自己解决问题的思路,还是有很多的可以提高的地方。
    2.之前练习的算法题,要时常回顾。现在发现,让自己现在去在脑海里做,
    思路都不是很明确。这样不行。
    3.自己想到的一些情况,也要代码去处理,而不是有特殊情况,自己直到,但是什么也没有做。
    应该写代码处理这些特殊情况。

    加油,少年。

  • 相关阅读:
    交互式监控工具glances
    性能测试工具Locust
    CentOS 7 安装 PostgreSQL 教程
    Vue表单
    Vue事件处理
    Vue列表渲染
    Vue条件渲染
    Vue中class与style绑定
    GIT命令操作
    Git简介
  • 原文地址:https://www.cnblogs.com/caoxinyu/p/10568508.html
Copyright © 2011-2022 走看看