今日题目:
这两天刷了这4道题,买卖股票的是动态规划的题目,之前总结过就不再总结了,直接放链接: 【前端er每日算法】动态规划--买卖股票一二
剩余2道总结一下,每道题都不止一种解法。
题目一 169. 多数元素
这道题目容易想起来的前2种解法:map计数和排序。后面的就不好想了。
解法一 map计数
遍历数组,map记录数字出现的次数,找到出现次数最多的值就是所求的值。
// map方法
var majorityElement = function(nums) {
const map = {};
let maxCount = 0;
let result = 0;
for (let i = 0; i < nums.length; i++) {
if (!map[nums[i]]) {
map[nums[i]] = 1;
} else {
map[nums[i]] += 1;
}
if (map[nums[i]] > maxCount) {
result = nums[i];
maxCount = map[nums[i]];
}
}
return result;
}
解法二 排序
数组排序,直接取n/2的值。
// 排序
var majorityElement = function(nums) {
nums.sort((a, b) => a - b);
return nums[Math.floor(nums.length / 2)];
};
解法三 Boyer-Moore 投票算法
看了题解后,发现还有好几种做法,觉得投票算法挺好的,所以记录下Boyer-Moore 投票算法。
算法思路:
-
维护一个候选数candicate和出现的次数。
-
遍历数组,对于每个元素
- 如果count为0,将元素赋值给candicate,该元素做为候选值。
- 然后将x和candidate判断
- 如果相等,则count+1
- 如果不等,count-1
-
遍历完成后,candicate就是数组的众数。
var majorityElement = function(nums) {
let candicate = -1;
let count = 0;
for (let i = 0; i < nums.length; i++) {
// 选一个作为候选值
if (count === 0) {
candicate = nums[i];
}
if (candicate === nums[i]) {
count++;
} else {
count--;
}
}
return candicate;
}
189. 轮转数组
这个题目也是多种解法,最简单的使用一个新数组的解法。这个简单就不写了,另外两种值得记录下:
解法一 反转再反转
- 先整体反转:后k个变成了前k个了
- 前k个反转:把前k个顺序变回来
- 后面剩余的元素反转:剩余的顺序再变回来。
齐活!完事,这个算法思路还是很有意思的。
function reverseStr(arr, left, right) {
while (left < right) {
[arr[left], arr[right]] = [arr[right], arr[left]];
left++;
right--;
}
}
var rotate = function(nums, k) {
const len = nums.length;
if (k > len) {
k = k % len;
}
reverseStr(nums, 0, len - 1);
reverseStr(nums, 0, k - 1);
reverseStr(nums, k, nums.length - 1);
return nums;
};
环状替换
这个还不太好想。就是循环替换,每次计算下一个位置赋值过去,将被替换的值保存下来,难的地方在于
-
啥时候停止?增加一个count计数,如果都替换过了跳出循环。
-
一次循环后如何啥时候停止?以为一圈到头可能还有元素没替换,所以转一圈到达起始位置后要加一,从下个元素开始,同时更新本圈的start值。
var rotate = function(nums, k) {
const len = nums.length;
if (k > len) {
k = k % len;
}
let count = 0;
let index = 0;
let last = nums[index];
let start = index;
// 记录移动的个数,如果不够长度,循环移动
while (count < len) {
// 计算应该移动到的位置,并保存下一个值
let next = (index + k) % len;
let temp = nums[next];
nums[next] = last;
last = temp;
index = next;
count++;
// 转回该圈起点的位置后index++,更新start和上一次的值
if (index === start) {
index++;
start = index;
last = nums[index];
}
}
return nums;
}