2021.9.20 力扣-数组美丽值求和

题目描述:

给你一个下标从 0 开始的整数数组 nums 。对于每个下标 i(1 <= i <= nums.length - 2),nums[i] 的 美丽值 等于:

2,对于所有 0 <= j < i 且 i < k <= nums.length - 1 ,满足 nums[j] < nums[i] < nums[k]
1,如果满足 nums[i - 1] < nums[i] < nums[i + 1] ,且不满足前面的条件
0,如果上述条件全部不满足
返回符合 1 <= i <= nums.length - 2 的所有 nums[i] 的 美丽值的总和 。

方法一:

class Solution {
public:
    int sumOfBeauties(vector& nums) {
        vector newnums;
        for (int num : nums)
        {
            newnums.push_back(num);
        }
        sort(newnums.begin(), newnums.end());
        int sum = 0;
        int maxnum = nums[0];   //记录前i个数字中的最大数字
        for (int i = 1; i < nums.size() - 1; i++)
        {
            if (nums[i] == newnums[i] && maxnum < nums[i] && newnums[i] != newnums[i - 1] && newnums[i] != newnums[i + 1])
            //第一次种情况如果nums[i]在数组newnums中也排在第i+1位,并且nums的前i个数字都小于nums[i],
            //并且没有多个与nums[i]相等的数字
            {
                sum += 2;
            }
            else if (nums[i] > nums[i - 1] && nums[i] < nums[i + 1])
            //否则就是第二种情况,只需判断nums[i]和前一个数字、后一个数字的大小关系
            {
                sum += 1;
            }
            maxnum = max(maxnum, nums[i]);
        }
        return sum;
    }
};

不谈暴力解,这题想了挺久也想不到O(n)的方法,后来觉得用sort()函数似乎可以,于是就试看看,一番修改之后终于过了。

 对数组nums排序得到newnums,那么对于nums[i]来说,满足:【如果nums[i]在数组newnums中也排在第i+1位,并且nums的前i个数字都小于nums[i],并且没有多个与nums[i]相等的数字】的是第一种情况,美丽值等于2;满足:【nums[i-1] < nums[i] < nums[i+1]】的是第二种情况,美丽值等于1。

参考下图:

2021.9.20 力扣-数组美丽值求和_第1张图片

例如对于3来说,它排在nums中的第三位,如果它要满足第一种情况,那么应该要有前面数字都小于3,后面的数字都大于3,所以在排序后的newnums 中3也应该排在第三位,可是在newnums中3不是排在第三位,所以其不满足第一种情况,然后再判断出不满足第二种情况,所以其美丽值等于0。

7则是一种特殊情况,因为它在nums中和在newnums中都排在相同的位置,但是显然它是不满足第一种情况的,因为其前面有个8,所以我使用了maxnum这个变量,记录下前i个数字中的最大值,如果maxnum > num[i],那么就说明nums[i]不满足第一种情况。

8是另外一种特殊情况,就是数组中有多个数字相同的时候,肯定是不会满足第一种情况的,那么我需要判断newnums[i]和newnums[i-1]、newnums[i+1]是否相等,如果相等就说明有多个与nums[i]相等的数字,

方法二:

class Solution {
public:
    int sumOfBeauties(vector& nums) {
        int sum = 0;
        int n = nums.size();
        vector premax(n);
        vector behmin(n);
        premax[0] = nums[0];
        behmin[0] = nums[0];
        premax[n - 1] = nums[n - 1];
        behmin[n - 1] = nums[n - 1];
        for (int i = 1; i < n - 1; i++)
        {
            premax[i] = max(premax[i - 1], nums[i]);
        }
        for (int i = n - 2; i >= 0; i--)
        {
            behmin[i] = min(behmin[i + 1], nums[i]);
        }
        for (int i = 1; i < n - 1; i++)
        {
            if (premax[i - 1] < nums[i] && nums[i] < behmin[i + 1])
            {
                sum += 2;
            }
            else if (nums[i - 1] < nums[i] && nums[i] < nums[i + 1])
            {
                sum += 1;
            }
        }
        return sum;
    }
};

经过淼淼的提醒之后,发现其实不用那么麻烦,我在方法一中使用了计算前缀最大数字的方法,那么只有再记录后缀最小数字就行了!

两次遍历,一次从前往后依次记录前i+1个数字的最小值,一次从后往前依次记录后n-i个数字的最大值。

最后再进行一次遍历,只要满足【premax[i - 1] < nums[i] && nums[i] < behmin[i + 1]】的就是第一种情况,否则满足【nums[i - 1] < nums[i] && nums[i] < nums[i + 1]】的就是第二种情况。

你可能感兴趣的:(leetcode,leetcode)