算法题(Java)02

274. H 指数

(✪▽✪)曼波~~~~ 让曼波来帮你解决这个问题吧!

曼波的思路:

题目要求找到研究者的h指数,即最大的h,使得至少有h篇论文的引用次数≥h次。曼波的解决步骤如下:

  1. 排序数组:首先将论文引用次数按升序排列。
  2. 遍历寻找h:从前往后遍历排序后的数组,计算当前可能的h值(n - i),若当前论文的引用次数≥h值,则h值即为所求。

代码实现:

import java.util.Arrays;

public class Solution {
    public int hIndex(int[] citations) {
        Arrays.sort(citations);
        int n = citations.length;
        for (int i = 0; i < n; i++) {
            int h = n - i;
            if (citations[i] >= h) {
                return h;
            }
        }
        return 0;
    }
}

曼波的解释:

  1. 排序:将数组排序后,可以方便地确定有多少篇论文的引用次数≥某个值。
  2. 遍历判断:对于每个位置i,计算h为总论文数减去i(即至少有h篇论文的引用次数≥h),一旦找到满足条件的h,立即返回最大的h值。

思维导图:

O(1) 时间插入、删除和获取随机元素

(✪▽✪)曼波~~~~ 曼波觉得这个方法是简单高效的哦!试试看吧~

思路

首先,我们需要在 O(1) 时间内完成插入、删除和随机访问。曼波的思路是这样的:

  1. 哈希表:用于快速查找元素是否存在,并记录元素在数组中的索引位置
  2. 动态数组:用于保存实际元素,方便随机访问
  3. 删除技巧:将要删除的元素与最后一个元素交换位置,然后删除最后一个元素,这样就能保持 O(1) 时间复杂度啦!

(๑・.・๑) 曼波觉得这个交换位置的思路是核心哦~ 这样删除中间元素时就不会破坏数组的连续性啦~

代码

import java.util.*;

class RandomizedSet {
    private Map<Integer, Integer> valToIndex;  // 值到索引的映射
    private List<Integer> values;              // 存储值的动态数组
    private Random rand;                       // 随机数生成器

    public RandomizedSet() {
        valToIndex = new HashMap<>();
        values = new ArrayList<>();
        rand = new Random();
    }
    
    public boolean insert(int val) {
        if (valToIndex.containsKey(val)) {
            return false;
        }
        // 把新元素添加到数组末尾,并记录索引
        valToIndex.put(val, values.size());
        values.add(val);
        return true;
    }
    
    public boolean remove(int val) {
        if (!valToIndex.containsKey(val)) {
            return false;
        }
        // 将最后一个元素移动到要删除的位置
        int index = valToIndex.get(val);
        int lastVal = values.get(values.size()-1);
        
        values.set(index, lastVal);  // 覆盖要删除的位置
        valToIndex.put(lastVal, index); // 更新最后一个元素的索引
        
        // 删除最后一个元素
        values.remove(values.size()-1);
        valToIndex.remove(val);
        
        return true;
    }
    
    public int getRandom() {
        return values.get(rand.nextInt(values.size()));
    }
}

曼波来画个思维导图解释下核心思路吧~

哦呜(° ロ °)!曼波觉得这个有点难哦(๑・.・๑),但如果是你一定没问题的,(✪▽✪)曼波~~

小贴士:

  • 删除时要注意当元素是最后一个的情况,但我们的代码已经自动处理啦
  • 随机访问的时间复杂度是严格的 O(1),因为数组支持随机访问
  • 用空间换时间,哈希表和数组的组合是常见的设计思路哦~

238. 除自身以外数组的乘积

(✪▽✪)曼波~~~~!曼波来帮你解决这个问题啦~这个问题需要计算除自身外的数组乘积,不能用除法,而且要高效哦!曼波觉得可以用前缀和后缀乘积的方法,分两步走呢~(๑✧◡✧๑)

步骤拆解:

  1. 计算左乘积数组:从左到右遍历,每个元素存储左边所有数的乘积。
  2. 计算右乘积并合并结果:从右到左遍历,用变量记录右边乘积,同时更新最终结果。

Java代码实现:

public int[] productExceptSelf(int[] nums) {
    int n = nums.length;
    int[] answer = new int[n];
    answer[0] = 1;
    // 计算左乘积
    for (int i = 1; i < n; i++) {
        answer[i] = answer[i - 1] * nums[i - 1];
    }
    // 计算右乘积并合并结果
    int rightProduct = 1;
    for (int i = n - 1; i >= 0; i--) {
        answer[i] *= rightProduct;
        rightProduct *= nums[i];
    }
    return answer;
}

曼波小贴士:

  • 时间复杂度:O(n),两次遍历搞定!
  • 空间复杂度:O(1)(输出数组不算额外空间哦~)

思维导图时间!用Markmap画个知识点总结吧~

(✪▽✪)曼波~~~~!是不是觉得这个方法很巧妙呢?遇到数组前后关联的问题,可以多想想前缀后缀法哦~(๑・.・๑)
 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值