数组的31-40题

1732. 找到最高海拔

有一个自行车手打算进行一场公路骑行,这条路线总共由 n + 1 个不同海拔的点组成。自行车手从海拔为 0 的点 0 开始骑行。

给你一个长度为 n 的整数数组 gain ,其中 gain[i] 是点 i 和点 i + 1 的 净海拔高度差(0 <= i < n)。请你返回 最高点的海拔 。

class Solution {
    public int largestAltitude(int[] gain) {
        int sum=0;
        int ans=0;
        for(int a :gain){
            sum+=a;
            ans=Math.max(ans,sum);
        }
        return ans;
    }
}

1464. 数组中两元素的最大乘积(找最大值和次大值)

给你一个整数数组 nums,请你选择数组的两个不同下标 i 和 j,使 (nums[i]-1)*(nums[j]-1) 取得最大值。

请你计算并返回该式的最大值。

class Solution {
    public int maxProduct(int[] nums) {
        Arrays.sort(nums);
        return (nums[nums.length - 1] - 1) * (nums[nums.length - 2] - 1);
    }
}
class Solution {
    public int maxProduct(int[] nums) {
        int a = nums[0], b = nums[1];
        if (a < b) {
            int temp = a;
            a = b;
            b = temp;
        }
        for (int i = 2; i < nums.length; i++) {
            if (nums[i] > a) {
                b = a;
                a = nums[i];
            } else if (nums[i] > b) {
                b = nums[i];
            }
        }
        return (a - 1) * (b - 1);
    }
}

2496. 数组中字符串的最大值

一个由字母和数字组成的字符串的 值 定义如下:

如果字符串 只 包含数字,那么值为该字符串在 10 进制下的所表示的数字。
否则,值为字符串的 长度 。
给你一个字符串数组 strs ,每个字符串都只由字母和数字组成,请你返回 strs 中字符串的 最大值 。

class Solution {
    public int maximumValue(String[] strs) {
        int res = 0;
        for (String s : strs) {//for增强循环
            boolean isDigits = true;//用来标记真假
            int n = s.length();//定义str中元素的长度
            for (int i = 0; i < n; ++i) {
                isDigits &= Character.isDigit(s.charAt(i));//&=用来计算是否为真,Character.isDigit 是 Java 中的一个静态方法,用于判断给定的字符是否是一个数字字符
            }
            res = Math.max(res, isDigits ? Integer.parseInt(s) : n);//为真是前面,为假是后面
        }
        return res;
    }
}

1979. 找出数组的最大公约数

给你一个整数数组 nums ,返回数组中最大数和最小数的 最大公约数 。

两个数的 最大公约数 是能够被两个数整除的最大正整数。

class Solution {
    public int findGCD(int[] nums) {
      // 排序数组
        Arrays.sort(nums);
        
        int n = nums.length;
        int a = nums[0]; // 最小的元素
        int b = nums[n - 1]; // 最大的元素

        // 使用辗转相除法计算最大公约数
        return gcd(a, b);
    }

    // 辗转相除法求最大公约数
    private int gcd(int a, int b) {
        while (b != 0) {
            int temp = b;
            b = a % b;
            a = temp;
        }
        return a;
    }
}

485. 最大连续 1 的个数

给定一个二进制数组 nums , 计算其中最大连续 1 的个数。

示例 1:

输入:nums = [1,1,0,1,1,1]
输出:3
解释:开头的两位和最后的三位都是连续 1 ,所以最大连续 1 的个数是 3.
示例 2:

class Solution {
    public int findMaxConsecutiveOnes(int[] nums) {
 int count = 0;  // 记录当前连续的 1 的个数
        int maxCount = 0;  // 记录最大连续 1 的个数

        for (int n : nums) {
            if (n == 0) {
                maxCount = Math.max(maxCount, count); // 更新最大连续 1 的个数
                count = 0; // 重新开始计数
            } else {
                count++; // 继续计数
            }
        }

        // 最后一个段可能是最大值
        maxCount = Math.max(maxCount, count);

        return maxCount;
    }
}

495. 提莫攻击

在《英雄联盟》的世界中,有一个叫 “提莫” 的英雄。他的攻击可以让敌方英雄艾希(编者注:寒冰射手)进入中毒状态。

当提莫攻击艾希,艾希的中毒状态正好持续 duration 秒。

正式地讲,提莫在 t 发起攻击意味着艾希在时间区间 [t, t + duration - 1](含 t 和 t + duration - 1)处于中毒状态。如果提莫在中毒影响结束 前 再次攻击,中毒状态计时器将会 重置 ,在新的攻击之后,中毒影响将会在 duration 秒后结束。

给你一个 非递减 的整数数组 timeSeries ,其中 timeSeries[i] 表示提莫在 timeSeries[i] 秒时对艾希发起攻击,以及一个表示中毒持续时间的整数 duration 。

返回艾希处于中毒状态的 总 秒数。

示例 1:

输入:timeSeries = [1,4], duration = 2
输出:4
解释:提莫攻击对艾希的影响如下:

  • 第 1 秒,提莫攻击艾希并使其立即中毒。中毒状态会维持 2 秒,即第 1 秒和第 2 秒。
  • 第 4 秒,提莫再次攻击艾希,艾希中毒状态又持续 2 秒,即第 4 秒和第 5 秒。
    艾希在第 1、2、4、5 秒处于中毒状态,所以总中毒秒数是 4
class Solution {
    public int findPoisonedDuration(int[] timeSeries, int duration) {
        int res = 0;
        int expired = 0;
        for (int i = 0; i < timeSeries.length; i++) {
            //未中毒 则相加
            if (timeSeries[i] >= expired) {
                res += duration;
            } else {
                //中毒情况下,不能叠加
                res += timeSeries[i] + duration - expired;
            }
            //下次中毒结束时间
            expired = timeSeries[i] + duration;
        }
        return res;
    }
}

414. 第三大的数

给你一个非空数组,返回此数组中 第三大的数 。如果不存在,则返回数组中最大的数。

示例 1:

输入:[3, 2, 1]
输出:1
解释:第三大的数是 1 。

class Solution {
    public int thirdMax(int[] nums) {

        // 初始化最大、次大和第三大的数
        long max = Long.MIN_VALUE;
        long second = Long.MIN_VALUE;
        long third = Long.MIN_VALUE;

        for (int num : nums) {
            // 用 long 类型来处理边界情况,防止溢出
            if (num > max) {
                third = second;
                second = max;
                max = num;
            } else if (num > second && num < max) {
                third = second;
                second = num;
            } else if (num > third && num < second) {
                third = num;
            }
        }

        // 检查是否找到第三大的数
        if (third == Long.MIN_VALUE) {
            return (int) max;
        } else {
            return (int) third;
        }
    }

628. 三个数的最大乘积

给你一个整型数组 nums ,在数组中找出由三个数组成的最大乘积,并输出这个乘积。

示例 1:

输入:nums = [1,2,3]
输出:6

官解最慢

class Solution {
    public int maximumProduct(int[] nums) {
        Arrays.sort(nums);
        int n = nums.length;
        return Math.max(nums[n-1]*nums[0]*nums[1],nums[n-1]*nums[n-2]*nums[n-3]);
    }
}

这样最快:(不理解)

class Solution {
    public int maximumProduct(int[] nums) {
        int max1=Integer.MIN_VALUE,max2=Integer.MIN_VALUE,max3=Integer.MIN_VALUE;
        int min1=Integer.MAX_VALUE,min2=Integer.MAX_VALUE;
        for(int i=0;i<nums.length;i++){
            int num = nums[i];
            if(num>max3){
                max3 = num;
                if(num>max2){
                    max3=max2;
                    max2=num;
                    if(num>max1){
                        max2 =max1;
                        max1 = num;
                    }
                }
            }
            if(num<min2){
                min2 = num;
                if(num<min1){
                    min2=min1;
                    min1=num;
                }
            }
        }

        if(min1==Integer.MAX_VALUE||max1<0){
            return max1*max2*max3;
        }else{
            return Math.max(max1*max2*max3,min1*min2*max1);
        }
    }
}

645. 错误的集合

集合 s 包含从 1 到 n 的整数。不幸的是,因为数据错误,导致集合里面某一个数字复制了成了集合里面的另外一个数字的值,导致集合 丢失了一个数字 并且 有一个数字重复 。

给定一个数组 nums 代表了集合 S 发生错误后的结果。

请你找出重复出现的整数,再找到丢失的整数,将它们以数组的形式返回。

示例 1:

输入:nums = [1,2,2,4]
输出:[2,3]

class Solution {
    public int[] findErrorNums(int[] nums) {
        int[] errorNums = new int[2];
        int n = nums.length;
        Arrays.sort(nums);
        int prev = 0;
        for (int i = 0; i < n; i++) {
            int curr = nums[i];
            if (curr == prev) {
                errorNums[0] = prev;
            } else if (curr - prev > 1) {
                errorNums[1] = prev + 1;
            }
            prev = curr;
        }
        if (nums[n - 1] != n) {
            errorNums[1] = n;
        }
        return errorNums;
    }
}

更快的:

class Solution {
    public int[] findErrorNums(int[] nums) {
        int[] result = new int[2];
        int n = nums.length;
        // 1.将[1,n]计数对应出现的次数
        int[] cnts = new int[n + 1];
        for (int x : nums) cnts[x]++;
        for (int i = 1; i <= n; i++) {
            // 2.如果某个数出现0次就是第二个数
            //   如果某个数出现2次就是第一个数
            if (cnts[i] == 0) result[1] = i;
            if (cnts[i] == 2) result[0] = i;
        }
        return result;
    }
}

697. 数组的度

给定一个非空且只包含非负数的整数数组 nums,数组的 度 的定义是指数组里任一元素出现频数的最大值。

你的任务是在 nums 中找到与 nums 拥有相同大小的度的最短连续子数组,返回其长度。

示例 1:

输入:nums = [1,2,2,3,1]
输出:2
解释:
输入数组的度是 2 ,因为元素 1 和 2 的出现频数最大,均为 2 。
连续子数组里面拥有相同度的有如下所示:
[1, 2, 2, 3, 1], [1, 2, 2, 3], [2, 2, 3, 1], [1, 2, 2], [2, 2, 3], [2, 2]
最短连续子数组 [2, 2] 的长度为 2 ,所以返回 2

思路及解法

记原数组中出现次数最多的数为 x,那么和原数组的度相同的最短连续子数组,必然包含了原数组中的全部 x,且两端恰为 x 第一次出现和最后一次出现的位置。

因为符合条件的 x 可能有多个,即多个不同的数在原数组中出现次数相同。所以为了找到这个子数组,我们需要统计每一个数出现的次数,同时还需要统计每一个数第一次出现和最后一次出现的位置。

在实际代码中,我们使用哈希表实现该功能,每一个数映射到一个长度为 3 的数组,数组中的三个元素分别代表这个数出现的次数、这个数在原数组中第一次出现的位置和这个数在原数组中最后一次出现的位置。当我们记录完所有信息后,我们需要遍历该哈希表,找到元素出现次数最多,且前后位置差最小的数。

代码

C++
Java
Python3
JavaScript
Golang
C
class Solution {
    public int findShortestSubArray(int[] nums) {
        Map<Integer, int[]> map = new HashMap<Integer, int[]>();
        int n = nums.length;
        for (int i = 0; i < n; i++) {
            if (map.containsKey(nums[i])) {
                map.get(nums[i])[0]++;
                map.get(nums[i])[2] = i;
            } else {
                map.put(nums[i], new int[]{1, i, i});
            }
        }
        int maxNum = 0, minLen = 0;
        for (Map.Entry<Integer, int[]> entry : map.entrySet()) {
            int[] arr = entry.getValue();
            if (maxNum < arr[0]) {
                maxNum = arr[0];
                minLen = arr[2] - arr[1] + 1;
            } else if (maxNum == arr[0]) {
                if (minLen > arr[2] - arr[1] + 1) {
                    minLen = arr[2] - arr[1] + 1;
                }
            }
        }
        return minLen;
    }
}
  • 11
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值