华为od机试
积木最远距离
题目描述
小华和小薇一起通过玩积木游戏学习数学。 他们有很多积木,每个积木块上都有一个数字,积木块上的数字可能相同。 小华随机拿一些积木挨着排成一排,请小薇找到这排积木中数字相同且所处位置最远的2块积木块,计算他们的距离,小薇请你帮忙替她解决这个问题。
输入描述
第一行输入为N,表示小华排成一排的积木总数。 接下来N行每行一个数字,表示小华排成一排的积木上数字。
备注
0<=积木上的数字<10^9
1<=积木长度<=10^5
function findFurthestBlocks(n, nums) {
let map = new Map(); // 记录每个数字最后出现的位置
let maxDist = -1; // 最远距离初始化为-1
for (let i = 0; i < n; i++) {
let num = nums[i];
if (map.has(num)) { // 若该数字不是第一次出现,则更新最远距离,并更新当前数字的最后出现位置
let dist = i - map.get(num);
if (maxDist < dist) maxDist = dist;
map.set(num, i);
} else { // 若该数字是第一次出现,则直接将其加入哈希表中
map.set(num, i);
}
}
return maxDist;
}
// 示例:7个积木分别是2 1 3 1 4 2 1,数字相同且位置最远的两块积木块上的数字是1,他们的距离是5(第2个积木与第7个积木)
console.log(findFurthestBlocks(7, [2, 1, 3, 1, 4, 2, 1]));
解析
- 使用哈希表记录每个数字最后出现的位置。若该数字已经出现过,则计算该数字上一次出现位置与当前位置之间的距离,并与已有的最远距离进行比较,取较大值更新最远距离;若该数字是第一次出现,则直接将其加入哈希表中。
- 遍历结束后,最远距离即为所求的结果。
租车骑绿岛
题目描述
部门组织绿岛骑行团建活动。租用公共双人自行车,每辆自行车最多坐两人,最大载重M。 给出部门每个人的体重,请问最多需要租用多少双人自行车。
输入描述
第一行两个数字m、n,分别代表自行车限重,部门总人数。第二行,n个数字,代表每个人的体重,体重都小于等于自行车限重m。
输出描述
最小需要的双人自行车数量。
function calculateBikes(m, n, weightList) {
let sortedWeightList = weightList.sort((a, b) => b - a); // 按体重从大到小排序
let count = 0; // 自行车数量统计
let i = 0, j = n - 1;
while (i <= j) { // 双指针法
if (sortedWeightList[i] + sortedWeightList[j] <= m) { // 若两人体重和小于等于限重,则可以坐一辆自行车
count++;
i++;
j--;
} else if (sortedWeightList[i] <= m) { // 若第一个人体重不超过限重,且无法与后面的人搭档,则只能单独租一辆自行车
count++;
i++;
} else { // 否则第一个人体重太重,无法搭档,只能单独租一辆自行车
return -1;
}
}
return count;
}
// 示例:自行车最大载重为150,有8个人且体重分别为50, 60, 70, 40, 30, 20, 80, 100,输出2
console.log(calculateBikes(150, 8, [50, 60, 70, 40, 30, 20, 80, 100]));
解析
- 首先对体重列表按体重从大到小排序,便于后续双指针遍历。
- 使用双指针法,一个指向列表头,一个指向列表尾,通过判断这两个指针所指元素的体重和是否小于等于自行车限重来确定是否需要租用一辆自行车。如果满足条件,则二者搭档骑车;否则,只有其中一个人单独骑车。其中,如果第一个人的体重太重,无法与任何一个人搭档,则不可能完成骑行活动,返回-1表示。
- 遍历结束后,得到最少需要的自行车数量,即为最终结果。
组装新的数组
题目描述
给你一个整数M和数组N,N中的元素为连续整数,要求根据N中的元素组装成新的数组R,组装规则:
- R中元素总和加起来等于M
- R中的元素可以从N中重复选取
- R中的元素最多只能有1个不在N中,且比N中的数字都要小(不能为负数)
输入描述
第一行输入是连续数组N,采用空格分隔
第二行输入数字M
输出描述
输出的是组装办法数量,int类型
备注
- 1 ≤ M ≤ 30
- 1 ≤ N.length ≤ 1000
function countMethods(m, n) {
let dp = new Array(m + 1).fill(0); // 动态规划数组初始化为0
dp[0] = 1; // 和为0只能选择不选,故dp[0]初始化为1
for (let i = 0; i < n.length; i++) {
for (let j = m; j >= n[i]; j--) { // 从大到小遍历可选取的元素
dp[j] += dp[j - n[i]];
}
}
return dp[m]; // 返回和为M的选择方案数
}
// 示例:N是1 2 3,M是5,满足要求的组装方案有5种
console.log(countMethods(5, [1, 2, 3]));
解析
- 使用动态规划求解,令dp[i]表示和为i的选择方案总数。则dp[i]可以由dp[i-n[j]]转移而来,其中n[j]为在N中可选的元素。
- 遍历完整个数组N后,dp[m]即为和为M的选择方案总数。