239. 滑动窗口最大值:
给你一个整数数组 nums
,有一个大小为 k
的滑动窗口从数组的最左侧移动到数组的最右侧。你只可以看到在滑动窗口内的 k
个数字。滑动窗口每次只向右移动一位。
返回 滑动窗口中的最大值 。
思路1:暴力解法——超时;每滑动一次就找窗口中找到最大值,时间复杂度是O(n*k);具体代码实现如下:
var maxSlidingWindow = function(nums, k) {
let left = 0;
let right = k-1;
let maxNums = [];
for(right; right < nums.length;){
let temp = left;
let max = nums[left];
while(temp<=right){
max = Math.max(max,nums[temp])
temp++
}
maxNums.push(max);
left++;
right++;
}
return maxNums
};
既然超时了,就需要分析怎么优化;上面代码中的while循环是是比了所有数,能不能减少比较的次数;情况1如果上一次在窗口中的数最大的值是中间的(非两端),是不是就可以直接用这个结果和下一次最右边的数对比就好了;情况2如果上一次在窗口中的最大数就是最左边的,这一次就不能利用上一次max的结果了,就只能保持原来的逻辑遍历所有的找最大值;具体代码实现如下:
var maxSlidingWindow = function(nums, k) {
if(k === 1){ // 如果窗口宽度是1就返回原数组;
return nums;
}
let left = 0; // 窗口左下标
let right = k-1; // 窗口右下标
let maxNums = []; // 放最大值的结果
let temp = left; // 将左边值赋给临时变量用于找最大值;
let max = nums[left]; // 单个窗口中的最大值;
let maxIndex = 0; // 单个窗口中的最大值的下标;
while(temp<=right){ // 找到第一个窗口中的最大值;
if(nums[temp]>=max){
max = nums[temp];
maxIndex = temp; // 更新最大值的下标
}
temp++
}
maxNums.push(max);
left++;
right++;
for(right; right < nums.length;){
if(left <= maxIndex){ // 最大值在上一次的非最左边
// 只需要比较上次最大值和最右边的值
if(max<nums[right]){
max = nums[right];
maxIndex = right;
}
} else { // 最大值在最左边
let temp1 = left;
max = nums[left];
while(temp1<=right){
if(nums[temp1]>=max){
max = nums[temp1];
maxIndex = temp1;
}
temp1++
}
}
maxNums.push(max);
left++;
right++;
}
return maxNums
};
优化之后可以通过,但是并非最优解;该题还可以尝试使用队列的思路,使用队列维护窗口中的递减队列,本次就不分享了后续再分享;
347. 前 K 个高频元素:给你一个整数数组 nums
和一个整数 k
,请你返回其中出现频率前 k
高的元素。你可以按 任意顺序 返回答案。
思路:将所有nums通过map统计出数字出现的频率,把所有的数据都排序一遍之后取前k个元素,返回即可;具体代码实现如下:
var topKFrequent = function(nums, k) {
let map = new Map();
let result = [];
for(item of nums){
if(map.has(item)){
map.set(item,map.get(item)+1)
} else {
map.set(item,1)
}
}
for(item of map){
result.push({item:item[0],val:item[1]})
}
result.sort((a,b)=> b.val-a.val)
result.splice(k);
return result.map(item=>item.item)
};
今天的分享就到这里了,谢谢;