LeetCode Day4 数组的改变、移动+二维数组

274.H指数

题目理解

给定研究者的论文引用数数组。H指数是指N篇论文中有H篇被引用了至少H次,其余N-H篇不超过H次。说白了就是统计数组中符合条件的那个最大值。举个例子,引用数组为[3,0,6,1,5],引用数>=0的有5篇,符合(0,0)条件;引用数>=1的有4篇。符合(1,1)条件;引用数>=2的有3篇,符合(2,2);引用数>=3的有3篇,符号(3,3);引用数>=4的有两篇,不符合(4,4)。

解题思路

①开始时考虑对数组进行从大到小排序,则排序后数组下标+1就相当于>=当前引用数的篇数。要寻找的是在(h,h)内的最大值。如果下标+1>数组当前元素则说明满足(h,h),因此问题改为了寻找排序后第一个下标+1>数组当前元素的数。涉及到排序,所以时间复杂度为O(NlogN).
②另一种思路是计数。显然H指数必小于等于文章数即数组长度n,因此将所有引用次数大于n的都变为n,不会影响结果。将每个引用次数出现的次数存下来,则比当前数组下标(即引用数)大的文章数,为当前数组元素之后的元素之和。因此循环时可以倒着来,进行累加。时间复杂度为O(n)。

代码

class Solution {
   
public:
    int hIndex(vector<int>& citations) {
   
        int n=citations.size();
        sort(citations.begin(),citations.end());//从小到大排序,所以循环得倒着来
        int i=0;
        for(;i<n;i++)
        {
   
            if(citations[n-1-i]<(i+1))
               break;
        }
        return i;
    }
};

class Solution {
   
public:
    int hIndex(vector<int>& citations) {
   
        int n=citations.size();
        vector<int> number(n+1,0);
        for(auto i:citations){
   
                ++number[min(i,n)];
        }
        int k=n;
        for(int s=number[n];s<k;s+=number[k])
            k--;
        return k;
    }
};

453最小操作数使数组元素相等

题目理解(不简单的简单题)

数组n个元素,每次操作给n-1个元素+1,求最小操作次数使数组元素相等。
如[1,2,3],只需要3次操作(注意每次操作会增加两个元素的值):
[1,2,3] => [2,3,3] => [3,4,3] => [4,4,4]

思路

①显然要使数组元素相等,每次+1的n-1个元素一定是数组中最小的n-1个元素。如果把数组排序,最小值一定是从始至终都在进行操作的数,且不用每次都加1,当前最小值一定会先加够最大值与最小值之间的差值,以[1,2,3]为例,最大为nums[n-1]=3,最小nums[0]=1,则至少+2,变为[3,4,3],当前最大值变为nums[n-2]=4,最小值仍然为nums[0],当前除最大值外的其他元素再加4-3=1,变为[4,4],操作次数为第一次的+2,第二次的+1,即为3.
②动态规划
仍然排序,一步一步考虑,每次都让前面的i-1的元素相等,则第i个元素,只需i-1前的元素再加上nums[i]-nums[i-1]。但数组毕竟是个整体,再给第一个第二个元素进行操作时,后面的元素也会同时进行操作。因此需要一个变量统计总的操作次数。
③数学方法
对n-1个最小元素+1,其实等效于对最大的元素-1,因此只需要找到让所有元素都减小到最小值的次数即为解。

代码

class Solution {
   
public:
    int minMoves(vector<int>& nums) {
   
        int n=nums.size();
        sort(nums.begin(),nums.end())
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
题目描述:给定一个非负整数数组nums和一个整数m,你需要将这个数组分成m个非空的连续子数组。设计一个算法使得这m个子数组中的最大和最小。 解题思路: 这是一个典型的二分搜索题目,可以使用二分查找来解决。 1. 首先确定二分的左右边界。左边界为数组中最大的值,右边界为数组中所有元素之和。 2. 在二分搜索的过程中,计算出分割数组的组数count,需要使用当前的中间值来进行判断。若当前的中间值不够分割成m个子数组,则说明mid值偏小,将左边界更新为mid+1;否则,说明mid值偏大,将右边界更新为mid。 3. 当左边界小于等于右边界时,循环终止,此时的左边界即为所求的结果。 具体步骤: 1. 遍历数组,找到数组中的最大值,并计算数组的总和。 2. 利用二分查找搜索左右边界,从左边界到右边界中间的值为mid。 3. 判断当前的mid值是否满足题目要求,若满足则更新右边界为mid-1; 4. 否则,更新左边界为mid+1。 5. 当左边界大于右边界时,循环终止,返回左边界即为所求的结果。 代码实现: ```python class Solution: def splitArray(self, nums: List[int], m: int) -> int: left = max(nums) right = sum(nums) while left <= right: mid = (left + right) // 2 count = 1 total = 0 for num in nums: total += num if total > mid: total = num count += 1 if count > m: left = mid + 1 else: right = mid - 1 return left ``` 时间复杂度分析:二分搜索的时间复杂度为O(logN),其中N为数组的总和,而遍历数组的时间复杂度为O(N),因此总的时间复杂度为O(NlogN)。

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值