多益笔试

65 阅读3分钟

第一个

数组中元素只有1,-1,求和大于0的最长子数组

代码

前缀和

mport java.util.HashMap;
import java.util.Map;

public class LongestSubarraySumGreaterThanZero {

    public static int findLongestSubarray(int[] nums) {
        // 用于存储前缀和及其第一次出现的索引
        Map<Integer, Integer> prefixSumMap = new HashMap<>();
        int maxLength = 0;  // 记录最长子数组的长度
        int currentSum = 0; // 当前前缀和

        // 初始化前缀和为0,起始索引为-1
        prefixSumMap.put(0, -1);

        // 遍历数组
        for (int i = 0; i < nums.length; i++) {
            currentSum += nums[i]; // 更新当前前缀和

            // 检查是否存在某个前缀和,使得当前前缀和减去它的结果大于0
            for (int sum : prefixSumMap.keySet()) {
                if (currentSum - sum > 0) {
                    maxLength = Math.max(maxLength, i - prefixSumMap.get(sum));
                }
            }

            // 如果当前前缀和是新的,则记录其第一次出现的索引
            if (!prefixSumMap.containsKey(currentSum)) {
                prefixSumMap.put(currentSum, i);
            }
        }

        return maxLength; // 返回最长子数组的长度
    }

    public static void main(String[] args) {
        int[] nums = {1, -1, 1, -1, 1, -1, 1};
        // 输出和大于0的最长子数组的长度
        System.out.println("和大于0的最长子数组长度为: " + findLongestSubarray(nums));
    }
}

思路概述

  1. 前缀和的概念

    • 前缀和是指从数组起始位置到当前位置的元素和。例如,对于数组 [1, -1, 1],其前缀和分别为 [1, 0, 1]
  2. 利用前缀和找子数组

    • 对于任意一个子数组 nums[i:j],它的和可以用前缀和计算:sum(nums[i:j]) = prefixSum[j] - prefixSum[i-1]。要找到和大于 0 的子数组,只需确保 prefixSum[j] - prefixSum[i-1] > 0
  3. 使用哈希表存储前缀和

    • 使用哈希表 prefixSumMap 记录每个前缀和第一次出现的索引。这样可以在 O(1) 时间内查询某个前缀和的索引。

详细步骤

  1. 初始化

    • 创建一个哈希表 prefixSumMap 来存储前缀和及其第一次出现的位置。
    • 初始化 currentSum 为 0(记录当前的前缀和)。
    • 将前缀和 0 和索引 -1 存入哈希表中。这表示在数组开始之前,前缀和为 0。
  2. 遍历数组

    • 对每个数组元素进行遍历,更新 currentSum 为当前元素的和。
    • 对于每个 currentSum,检查哈希表中的所有前缀和。如果 currentSum - sum > 0,则计算子数组的长度,更新 maxLength 为当前最长的满足条件的子数组长度。
  3. 更新哈希表

    • 如果当前的 currentSum 还没有在哈希表中出现,则将其存储到哈希表中,记录当前的索引。
  4. 返回结果

    • 遍历完成后,maxLength 将保存和大于 0 的最长子数组的长度。

第二个

给定一个函数random(),该函数返回0-1间的浮点数。现要求使用该函数构造函数sample,从长度为n的序列pool中随机抽取k个元素(避免抽取重复元素)

代码

import java.util.ArrayList;
import java.util.List;

public class RandomSampler {
    public static List<Integer> sample(List<Integer> pool, int k) {
        List<Integer> sampled = new ArrayList<>();
        while (sampled.size() < k) {
            int index = (int) (Math.random() * pool.size());
            if (!sampled.contains(index)) {
                sampled.add(pool.get(index));
            }
        }
        return sampled;
    }

    public static void main(String[] args) {
        // 示例使用
        List<Integer> pool = new ArrayList<>();
        for (int i = 0; i < 10; i++) {
            pool.add(i); // 假设pool是0到9的整数序列
        }
        int k = 5; // 假设我们想抽取5个元素
        List<Integer> result = sample(pool, k);
        System.out.println(result);
    }
}

初始化:创建一个 ArrayList 来存储抽取的元素。

循环抽取:使用一个循环结构来抽取 k 个元素。

生成随机索引:在循环中,使用 Math.random() 来生成一个随机数,然后映射到 0 到 n-1 的范围内。

避免重复:生成随机索引后,检查该索引是否已经用于抽取元素。如果是,重新生成随机索引。

添加元素:如果索引是新的,将对应索引的元素添加到 ArrayList 中。

返回结果:当抽取了 k 个元素后,返回这个 ArrayList。