继上次给大家分享的刷题解析和经验分享,这次继续这个系列,这个系列预计有五期,今天给大家带来第二期的分享。
今天的第一题------比赛的赢家
问题描述
小M正在玩一个数组比赛游戏,每回合游戏都在所有元素互不相同的数组 arr
的前两个元素 arr[0]
和 arr[1]
之间进行。较大的整数将会取得这一回合的胜利并保留在位置 0,而较小的整数则会被移至数组的末尾。比赛继续,直到某个整数连续赢得 k
次,这个整数即为比赛的赢家。给定一个整数数组 arr
和一个整数 k
,请返回赢得比赛的整数。题目数据保证游戏中一定存在赢家。
测试样例
-
样例1:
- 输入:
arr = [2, 1, 3, 5, 4, 6, 7, 9], k = 2
- 输出:
5
- 输入:
-
样例2:
- 输入:
arr = [3, 2, 1, 4], k = 10
- 输出:
4
- 输入:
-
样例3:
- 输入:
arr = [1, 9, 8, 7, 6, 5, 4, 3, 2, 11], k = 7
- 输出:
9
- 输入:
解决方案
我们可以使用循环队列的思想来模拟整个过程。每次比较前两个元素,然后根据规则移动元素。同时,我们需要跟踪当前获胜者和连胜次数。当连胜次数达到 k
时,我们找到了赢家。
js
function solution(arr, k) {
let consecutiveWins = 0;
let currentWinner = arr[0];
while (true) {
if (arr[0] > arr[1]) {
// 如果第一个元素大于第二个元素
arr.push(arr.splice(1, 1)[0]); // 第二个元素移到最后
} else {
// 如果第二个元素大于第一个元素
arr.push(arr.shift()); // 第一个元素移到最后
}
// 更新当前赢家和赢的次数
if (currentWinner === arr[0]) {
consecutiveWins++;
} else {
currentWinner = arr[0];
consecutiveWins = 1;
}
if (consecutiveWins === k) {
return currentWinner;
}
}
}
// 测试用例
console.log(solution([2, 1, 3, 5, 4, 6, 7, 9], 2)); // 输出: 5
console.log(solution([3, 2, 1, 4], 10)); // 输出: 4
console.log(solution([1, 9, 8, 7, 6, 5, 4, 3, 2, 11], 7)); // 输出: 9
核心逻辑:
- 无限循环:使用 while (true) 来持续进行比赛,直到某一个数字连续赢得 k 次。
- 比较前两个元素:
- 如果 arr[0] 大于 arr[1],则 arr[0] 赢得这一回合,将 arr[1] 移到数组末尾(使用 arr.push(arr.splice(1, 1)[0]))。
- 否则,arr[1] 赢得这一回合,将 arr[0] 移到数组末尾(使用 arr.push(arr.shift()))。
- 更新赢家信息:
- 如果当前获胜者 currentWinner 仍然是 arr[0] 的话,则增加 consecutiveWins。
- 否则,意味着有新的赢家出现,重置 currentWinner 为 arr[0] 并且 consecutiveWins 设置为 1。
- 检查连胜次数: 如果 consecutiveWins 达到了 k,那么当前的 currentWinner 就是我们要找的答案,返回 currentWinner。 测试用例:通过几个测试用例来验证算法的正确性。
第二题------雇主的招聘问题
问题描述
小U作为一位雇主,想要招聘一位工人。现有 n
个人前来应聘,每个人都写下了他们期望的薪资。小U打算选择期望薪资最低的人,但为了避免纠纷,他只会选择在没有其他人提出相同期望薪资的情况下期望薪资最低的人。如果没有符合条件的人,他将不录用任何人。你的任务是帮助小U找到合适的最低薪资。如果没有合适的人,输出 -1
。
测试样例
-
样例1:
- 输入:
n = 3, salaries = [3, 2, 1]
- 输出:
1
- 输入:
-
样例2:
- 输入:
n = 6, salaries = [1, 1, 4, 5, 1, 4]
- 输出:
5
- 输入:
-
样例3:
- 输入:
n = 3, salaries = [4, 4, 4]
- 输出:
-1
- 输入:
解决方案
这个问题可以通过先对薪资数组进行排序,然后从最低的薪资开始检查,寻找第一个没有重复的薪资值。如果所有的薪资都重复,则返回 -1
。
js
function findUniqueMinSalary(salaries) {
const sortedSalaries = [...salaries].sort((a, b) => a - b);
for (let i = 0; i < sortedSalaries.length; i++) {
// 检查当前元素是否是唯一的
if ((i === 0 || sortedSalaries[i] !== sortedSalaries[i - 1]) &&
(i === sortedSalaries.length - 1 || sortedSalaries[i] !== sortedSalaries[i + 1])) {
return sortedSalaries[i];
}
}
return -1;
}
// 测试用例
console.log(findUniqueMinSalary([3, 2, 1])); // 输出: 1
console.log(findUniqueMinSalary([1, 1, 4, 5, 1, 4])); // 输出: 5
console.log(findUniqueMinSalary([4, 4, 4])); // 输出: -1
核心思路:
- 复制和排序:
- 首先,我们使用扩展运算符 ... 来创建 salaries 数组的一个浅拷贝,并将其存储在 sortedSalaries 变量中。
- 然后,我们使用 Array.prototype.sort() 方法对 sortedSalaries 进行升序排序。这样可以确保最小的薪资出现在数组的最前面。
- 遍历查找唯一值:
- 我们遍历排序后的 sortedSalaries 数组。
- 对于每个元素,我们检查它是否是唯一的。为了做到这一点,我们需要检查该元素是否与它的前一个元素不同(sortedSalaries[i] !== sortedSalaries[i - 1]),并且与它的下一个元素也不同(sortedSalaries[i] !== sortedSalaries[i + 1])。
- 如果满足上述条件,说明这个元素是唯一的,我们立即返回它作为结果。
- 边界情况处理:
- 当我们在数组的第一个位置时(i === 0),不需要比较前一个元素。
- 当我们在数组的最后一个位置时(i === sortedSalaries.length - 1),不需要比较后一个元素。
当然,这种解法是有一点缺陷的,如果薪资列表非常大,排序可能会消耗较多时间。 如果数据集中有大量重复值,排序可能不是最优解法,因为即使大部分值都不是唯一值,我们仍然需要进行完整的排序。
那大家可以想想有没有别的方法呢?我最近比较忙,暂时就先提供这一种思路吧,大家可以在评论区发表自己的看法哦
好了,这次分享就到这里了。