首页 > 其他分享 >day10

day10

时间:2024-06-11 20:13:48浏览次数:24  
标签:map nums int 元素 queue num day10

今天是day10
题目一:滑动窗口最大值,要求从一个大小为k的滑动窗口从数组的最左端移动到数组的最右侧最终返回窗口中的最大值

from collections import deque
class MyQueue:
    def __init__(self):
        "双端队列"
        self.queue = deque()

    def pop(self,value):
        "确保队列不为空且要弹出的值等于队列中的第一个值"
        "因为队列是单调递减的,所以当队列的第一个值等于当前要弹出的值时,这个值应该是队列中最大的值。"
        if self.queue and value == self.queue[0]:
            self.queue.popleft()
    def push(self,value):
        "确保队列不为空且当前要添加的值大于队列中最后一个值"
        "因为当前值大于队尾值,所以队尾值不可能成为滑动窗口中的最大值,需要被移除。"
        while self.queue and value > self.queue[-1]:
            self.queue.pop()
        "将当前值添加到队列的右端,保持队列的单调递减性质"
        self.queue.append(value)
    
    def front(self):
        return self.queue[0]
class Solution:
    def maxSlidingWindow(self, nums: List[int], k: int) -> List[int]:
        que = MyQueue()
        result = []
        "对于给定的滑动数组长度进行分割将值直接推入队列"
        for i in range(k):
            que.push(nums[i])
        "此时确保了队列的值的单调,即第一个数值必定为最大值,故直接将其加入至result中"
        result.append(que.front())
        "如下几步实现了滑动"
        for i in range(k,len(nums)):
            que.pop(nums[i-k])
            que.push(nums[i])
            result.append(que.front())
        return result
type MyQueue struct {
    queue []int
}
//初始化声明一个数组
func NewMyQueue() *MyQueue{
    return &MyQueue{
        queue:make([]int,0),
    }
}

//取数组的第一个元素
func (m *MyQueue) Front() int{
    return m.queue[0]
}
//取数组的最后一个元素
func (m *MyQueue) Back() int{
    return m.queue[len(m.queue)-1]
}
//判空
func (m *MyQueue) Empty() bool {
    return len(m.queue) == 0
}
//确保队列不为空且当前要添加的值大于队列中最后一个值,因为当前值大于队尾值,所以队尾值不可能成为滑动窗口中的最大值,需要被移除
func (m *MyQueue) Push(val int) {
    for !m.Empty()&& val > m.Back() {
        m.queue = m.queue[:len(m.queue)-1]
    }
    m.queue = append(m.queue,val)
}
//因为队列是单调递减的,所以当队列的第一个值等于当前要弹出的值时,这个值应该是队列中最大的值
func (m *MyQueue) Pop(val int) {
    if !m.Empty() && val == m.Front() {
        m.queue = m.queue[1:]
    }
}
func maxSlidingWindow(nums []int, k int) []int {
     queue :=NewMyQueue()
     length := len(nums)
     res := make([]int,0)
     for i:=0;i<k;i++{
        queue.Push(nums[i])
     }
     res = append(res,queue.Front())
     for i:=k;i<length;i++{
        queue.Pop(nums[i-k])
        queue.Push(nums[i])
        res = append(res,queue.Front())
     }
     return res
}

题目二:
前k个高频元素,给定一个非空的整数数组,返回其中的出现频率前k个高的元素

"导入 Python 的 heapq 模块,该模块提供了堆(heap)相关的函数和类。"
import heapq
class Solution:
    def topKFrequent(self, nums: List[int], k: int) -> List[int]:
        map_ = {}
        "统计数组中每个元素的出现频率,并将其存储在字典 map_ 中。如果字典中不存在该元素,则初始化其出现频率为 0,然后加 1。"
        for i in range(len(nums)):
            map_[nums[i]] = map_.get(nums[i],0) + 1
        
        "创建了一个空列表 pri_que,用于存储元素频率和元素值的元组,并将其作为堆(heap)使用。"
        pri_que = []
        "将元素的频率和值作为一个元组 (freq, key),压入堆 pri_que 中。由于 Python 的堆默认是最小堆(即根节点的值最小),所以这里存储的是 (频率, 元素值) 的元组。"
        for key,freq in map_.items():
            heapq.heappush(pri_que,(freq,key))
            "如果堆的大小超过了 k,则执行下面的操作。这是为了保持堆中始终只有前 k 高的元素。"
            if len(pri_que) > k:
                heapq.heappop(pri_que)
        
        result = [0] * k
        "逆向遍历 result 列表,从后向前依次填充元素。"
        for i in range(k-1,-1,-1):
            "将堆 pri_que 中的元素依次弹出,并将其值(即元素值)赋给 result[i],这样 result 列表中存储的就是出现频率前 k 高的元素。"
            result[i] = heapq.heappop(pri_que)[1]
        return result
class Solution:
    def topKFrequent(self, nums: List[int], k: int) -> List[int]:
        time_dict = defaultdict(int)
        for num in nums:
            "更新字典 time_dict 中元素 num 的出现频率,如果 num 不在字典中,则默认值为 0。"
            time_dict[num] +=1
        index_dict = defaultdict(list)
        for key in time_dict:
            "将元素 key 添加到字典 index_dict 中对应频率的列表中。"
            index_dict[time_dict[key]].append(key)
        "获取字典 index_dict 的所有键(即出现的频率),并转换为列表。"
        key = list(index_dict.keys())
        "频率小的元素会排在列表的前面。"
        key.sort()
        result = []
        cnt = 0
        "循环条件是频率列表不为空且已经添加到 result 中的元素个数不等于 k。"
        while key and cnt != k:
            "将频率列表中最大的频率对应的元素列表添加到 result 中。"
            result += index_dict[key[-1]]
            "更新已经添加到 result 中的元素个数。"
            cnt += len(index_dict[key[-1]])
            "弹出频率列表中最大的频率。"
            key.pop()
        "返回 result 列表中前 k 个元素,即出现频率前 k 高的元素。"
        return result[0:k]
//这行定义了一个新的类型 IHeap,它是一个切片,每个元素是长度为 2 的整数数组
type IHeap [][2] int
//这段代码定义了类型 IHeap 的方法 Len(),返回切片的长度,它实现了 heap.Interface 接口的 Len() 方法
func (h IHeap) Len() int {
    return len(h)
}
//这段代码定义了类型 IHeap 的方法 Less(),用于定义堆的排序规则。这里是根据切片中元素的第二个值进行比较,从小到大排序。它实现了 heap.Interface 接口的 Less() 方法。
func (h IHeap) Less(i,j int) bool {
    return h[i][1] < h[j][1]
}
//这段代码定义了类型 IHeap 的方法 Swap(),用于交换切片中的两个元素。它实现了 heap.Interface 接口的 Swap() 方法。
func (h IHeap) Swap(i,j int) {
    h[i],h[j] = h[j],h[i]
}
//这段代码定义了类型 IHeap 的方法 Push(),用于向堆中添加元素。它首先将接收到的元素类型转换为 [2]int,然后将其追加到切片中。
func (h *IHeap) Push(x interface{}) {
    *h = append(*h,x.([2]int))
}
//这段代码定义了类型 IHeap 的方法 Pop(),用于从堆中弹出元素。它首先保存当前堆的副本,然后获取最后一个元素,并将切片的长度减少 1。最后,返回被弹出的元素。
func (h *IHeap) Pop() interface{} {
    old:=*h
    n:=len(old)
    x:=old[n-1]
    *h = old[0:n-1]
    return x
}
//这段代码是解决「前 K 个高频元素」问题的主要函数。它首先创建了一个映射 map_num,用于存储每个元素的频率。然后创建了一个 IHeap 类型的指针 h,并通过 heap.Init() 方法将其初始化为空堆。
func topKFrequent(nums []int, k int) []int {
     map_num := map[int]int{}
     for _,item := range nums{
        map_num[item] ++
     }
     h:=&IHeap{}
     heap.Init(h)
     //这是一个循环,遍历了 map_num 中的键值对,即元素及其频率。
     for key,value := range map_num{
        //将元素及其频率作为一个长度为 2 的数组 [2]int 添加到堆 h 中。
        heap.Push(h,[2]int{key,value})
        //如果堆的长度超过了 k,则执行以下操作:heap.Pop(h):从堆中弹出一个元素,因为我们只需要前 k 个高频元素。
        if h.Len()>k{
            heap.Pop(h)
        }
     }
     //创建一个长度为 k 的整数切片 res,用于存储前 k 个高频元素。遍历 res 中的每个位置。从堆中弹出元素 [2]int,并将其中的第一个值(元素本身)存储到 res 中。这里之所以使用 k-i-1 是因为堆是按照从小到大排序的,而我们需要的是前 k 个高频元素,所以要从 res 的末尾开始存储。
     res:=make([]int,k)
     for i:=0;i<k;i++{
        res[k-i-1] = heap.Pop(h).([2]int)[0]
     }
     return res
}
func topKFrequent(nums []int, k int) []int {
    ans:=[]int{}
//初始化一个映射 map_num,用于统计每个数字在切片 nums 中出现的次数。
    map_num:=map[int]int{}
    //遍历切片 nums 中的每个元素 item,并将元素作为键存储在 map_num 中,值为该元素出现的次数。这样,map_num 就记录了 nums 中每个元素的频率。
    for _,item:=range nums {
        map_num[item]++
    }
   //遍历 map_num 中的键(即切片 nums 中的元素),并将键添加到结果切片 ans 中。这样,ans 中存储的是 nums 中出现过的不重复的元素。
    for key,_ := range map_num{
        ans = append(ans,key)
    }
//使用 sort.Slice 函数对切片 ans 进行排序。排序的方式是根据每个元素在 map_num 中对应的值(即元素在 nums 中出现的频率)进行降序排序。
    sort.Slice(ans,func (a,b int) bool {
        return map_num[ans[a]] > map_num[ans[b]]
    })
    //返回排序后的结果切片 ans 的前 k 个元素,即出现频率最高的前 k 个元素。
    return ans[:k]

}

标签:map,nums,int,元素,queue,num,day10
From: https://www.cnblogs.com/leisure535/p/18242631

相关文章

  • day10 BS4
    re.findall("规则","待匹配字符串",模式)re.search/group//指定拿什么数据上一节补充:withopen伴随打开asf赋值聚鼎s=f.read//所有字符串打印出来赋值给sre.S通配符能够匹配包括换行符的一切r"\d+"原生字符串解析所有的数字re.search只第一个匹配条件的re.......
  • 代码随想录算法训练营day10(栈与队列)
    代码随想录算法训练营day10(栈与队列):学习内容:std::queue和std::stack是C++标准库中提供的队列和栈的容器适配器,它们分别基于队列和栈的概念,提供了一组简单的操作接口。std::queuestd::queue是一个先进先出(FIFO)的队列容器适配器。它提供了队列的基本操作,包括入队(pus......
  • day10今日笔记
    今日笔记grepgrep是对数据进行过滤查找关键字源数据可以是文件内容grephello/opt/hello.txt,找出存在hello的那一行命令的执行结果,这个需要结合管道符使用,cat/etc/passwd|grep'root'测试数据Iteachlinux.Ilikepython.Myqqis877348180.Mynameis......
  • m1_day10
    课程内容:String类常见的面试题String类常见的20个方法String类常见的面试题:new和不new之间的区别?Stringx="etoak"; Stringy=newString("etoak");不new的方式涉及到常量池查找机制永远先去常量池查看是否缓存过如果缓存过那么直接将值取出来使用如果没......
  • day10_01_我的Java学习笔记 (JavaSE进阶课程预备)
    JavaSE进阶课程预备1.JavaSE加强课程简介2.IDEA开发模式统一工程,相当于一个小区的院子;模块,是小区的哪一栋;包,是这栋楼的那一单元类,是这个单元的哪一层楼;对象,是这层楼具体的某一户房间。eg:滢水山庄二区--工程9栋--模块4单元--包8楼--类......
  • day10_02_我的Java学习笔记 (JavaSE加强课程介绍、先建空工程--再建模块--然后建包--
    JavaSE基础加强课程介绍1.JavaSE加强课程简介2.IDEA开发模式统一工程,相当于一个小区的院子;模块,是小区的哪一栋;包,是这栋楼的那一单元类,是这个单元的哪一层楼;对象,是这层楼具体的某一户房间。eg:溪山美地二区--工程9栋--模块4单元--包8楼--......
  • JAVA语言学习-Day10、11、12
    参考教学视频:秦疆learnJava-JUC1.什么是JUCjava.util工具包、包、分类java.util.concurrentjava.util.concurrent.atomicjava.util.concurrent.locks2.线程和进程举例:开启一个Typora(进程),输入、自动保存(线程)进程:一个程序一个进程往往可以包含多个线程,至少包含一个线程:写......
  • LeetCode刷题记录——day10
    1、https://leetcode.cn/problems/rotate-image/description/?envType=study-plan-v2&envId=2024-spring-sprint-100classSolution{public:voidrotate(vector<vector<int>>&matrix){intn=matrix.size();for(inti=0;......
  • 就业班 第二阶段 2401--4.1 day10 shell之“三剑客”+Expect
    十一、shell编程-grepegrep支持正则表达式的拓展元字符(或grep -E)#egrep'[0-9]{1,3}.[0-9]{1,3}.[0-9]{1,3}.[0-9]{1,3}'file1.txt[root@newrain~]#num1=11、运用正则,判断需要[[]][root@newrain~]#[[$num1=~^[0-9]+$]]&&echo"yes"||echo"n......
  • Leetcode算法训练日记 | day10
    一、用栈实现队列1.题目Leetcode:第232题请你仅使用两个栈实现先入先出队列。队列应当支持一般队列支持的所有操作(push、pop、peek、empty):实现MyQueue类:voidpush(intx)将元素x推到队列的末尾intpop()从队列的开头移除并返回元素intpeek()返回队列开头的元素......