第一个
数组中元素只有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, 0, 1]。
- 前缀和是指从数组起始位置到当前位置的元素和。例如,对于数组
-
利用前缀和找子数组:
- 对于任意一个子数组
nums[i:j],它的和可以用前缀和计算:sum(nums[i:j]) = prefixSum[j] - prefixSum[i-1]。要找到和大于 0 的子数组,只需确保prefixSum[j] - prefixSum[i-1] > 0。
- 对于任意一个子数组
-
使用哈希表存储前缀和:
- 使用哈希表
prefixSumMap记录每个前缀和第一次出现的索引。这样可以在 O(1) 时间内查询某个前缀和的索引。
- 使用哈希表
详细步骤
-
初始化:
- 创建一个哈希表
prefixSumMap来存储前缀和及其第一次出现的位置。 - 初始化
currentSum为 0(记录当前的前缀和)。 - 将前缀和 0 和索引 -1 存入哈希表中。这表示在数组开始之前,前缀和为 0。
- 创建一个哈希表
-
遍历数组:
- 对每个数组元素进行遍历,更新
currentSum为当前元素的和。 - 对于每个
currentSum,检查哈希表中的所有前缀和。如果currentSum - sum > 0,则计算子数组的长度,更新maxLength为当前最长的满足条件的子数组长度。
- 对每个数组元素进行遍历,更新
-
更新哈希表:
- 如果当前的
currentSum还没有在哈希表中出现,则将其存储到哈希表中,记录当前的索引。
- 如果当前的
-
返回结果:
- 遍历完成后,
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。