leetcode-堆


一、堆

1. 堆的定义

根据 维基百科 的定义, 是一种特别的二叉树,满足以下条件的二叉树,可以称之为 :(优先队列)

  1. 完全二叉树;(特点:叶子结点只能出现在最下层和次下层,且最下层的叶子结点集中在树的左部。需要注意的是,满二叉树肯定是完全二叉树,而完全二叉树不一定是满二叉树。)
  2. 每一个节点的值都必须 大于等于或者小于等于 其孩子节点的值。(即最大堆或最小堆)
    具有以下的特点:
  3. 可以在 O ( l o g N ) O(logN) O(logN)的时间复杂度内向 中插入元素;
  4. 可以在 O ( l o g N ) O(logN) O(logN)的时间复杂度内向 中删除元素;
  5. 可以在 O ( 1 ) O(1) O(1) 的时间复杂度内获取 中的最大值或最小值。
    在这里插入图片描述

2.堆的插入

  1. 最小堆的插入
    在这里插入图片描述
    在这里插入图片描述
    插入的过程必须满足(的定义)
    在这里插入图片描述
    在这里插入图片描述
    在这里插入图片描述
    最后满足堆的定义,构造成新的最小堆。

  2. 最大堆的插入
    在这里插入图片描述
    在这里插入图片描述
    在这里插入图片描述
    此时就将15插入到最大堆中。

  3. 最小堆的删除
    一般来说堆的删除都是删除堆顶元素。
    在这里插入图片描述
    在这里插入图片描述
    将最后一个元素替换堆顶元素,并删除最后一个元素。
    在这里插入图片描述
    需要满足最小堆的特性。
    在这里插入图片描述
    这样就得到一个新的最小堆。

  4. 最大堆的删除
    在这里插入图片描述
    最后的元素替换第一个元素,并删除最后一个元素。
    在这里插入图片描述
    在这里插入图片描述
    这样就得到一个新的最大堆。

二、题库

1.堆的实现(最大堆python)

# 「最大堆」的实现
import sys
class MaxHeap:
    def __init__(self, heapSize):
        # heapSize用于数组的大小,因为数组在创建的时候至少需要指明数组的元素个数
        self.heapSize = heapSize
        # 使用数组创建完全二叉树的结构,然后使用二叉树构建一个「堆」  
        self.maxheap = [0]*(heapSize+1)
        # realSize用于记录「堆」的元素个数
        self.realSize = 0
    #  添加元素函数
    def add(self, element):
        self.realSize += 1
        # 如果「堆」中元素的个数大于一开始设定的数组的个数,则返回「Add too many elements」
        if self.realSize > self.heapSize:
            print("Add too many elements!")
            self.realSize -= 1
            return
        # 将添加的元素添加到数组中
        self.maxheap[self.realSize] = element
        # 新增元素的索引位置
        index = self.realSize
        # 新增元素的父节点的索引位置
        # 注意,如果用数组表示完全二叉树,并且根结点存储在数组的索引1的位置的时候,任何一个节点的父节点索引位置为「该节点的索引位置/2」,任何一个节点的左孩子节点的索引位置为「该节点的索引位置*2」,任何一个节点的右孩子节点的索引位置为「该节点的索引位置*2+1」
        parent = index // 2
        # 当添加的元素大于父节点时,需要将父节点的值和新增元素的值交换
        while (self.maxheap[index] > self.maxheap[parent] and index > 1):
            self.maxheap[parent], self.maxheap[index] = self.maxheap[index], self.maxheap[parent]
            index = parent
            parent = index // 2
    # 获取堆顶元素函数
    def peek(self):
        return self.maxheap[1]
    
    # 删除堆顶元素函数
    def pop(self):
        # 如果当前「堆」的元素个数为0, 则返回「Don't have any element」
        if self.realSize < 1:
            print("Don't have any element!")
            return sys.maxsize
        else:
            # 当前「堆」中含有元素
            # self.realSize >= 1
            removeElement = self.maxheap[1]
            # 将「堆」中的最后一个元素赋值给堆顶元素
            self.maxheap[1] = self.maxheap[self.realSize]
            self.realSize -= 1
            index = 1
            # 当删除的元素不是孩子节点时
            while (index < self.realSize and index <= self.realSize // 2):
                # 被删除节点的左孩子节点
                left = index * 2
                # 被删除节点的右孩子节点
                right = (index * 2) + 1
                # 当删除节点的元素小于 左孩子节点或者右孩子节点,代表该元素的值小,此时需要将该元素与左、右孩子节点中最大的值进行交换
                if (self.maxheap[index] < self.maxheap[left] or self.maxheap[index] < self.maxheap[right]):
                    if self.maxheap[left] > self.maxheap[right]:
                        self.maxheap[left], self.maxheap[index] = self.maxheap[index], self.maxheap[left]
                        index = left
                    else:
                        self.maxheap[right], self.maxheap[index] = self.maxheap[index], self.maxheap[right]
                        index = right
                else:
                    break
            return removeElement
    
    # 返回「堆」的元素个数
    def size(self):
        return self.realSize
    
    def toString(self):
        print(self.maxheap[1 : self.realSize+1])
        
if __name__ == "__main__":
    	# 测试用例
        maxHeap = MaxHeap(5)
        maxHeap.add(1)
        maxHeap.add(2)
        maxHeap.add(3)
        # [3,1,2]
        maxHeap.toString()
        # 3
        print(maxHeap.peek())
        # 3
        print(maxHeap.pop())
        # 2
        print(maxHeap.pop())
        # 1
        print(maxHeap.pop())
        maxHeap.add(4)
        maxHeap.add(5)
        # [5,4]
        maxHeap.toString()

2.堆的常用方法

1.创建堆

创建堆指的是初始化一个堆实例(python库(heapq:只有最小堆无最大堆))
时间复杂度: O ( N ) O(N) O(N)
空间复杂度: O ( N ) O(N) O(N
Python 最小堆转换城最大堆的逻辑
就是将元素进行取反,如[1,2,3]。[-1,-2,-3],这时候建立最小堆即可,就满足最大堆的逻辑。

  1. 插入元素
    插入操作指的是向 堆 中插入一个新元素。值的注意的是,新元素插入完毕后,堆 依旧需要维持它的特性。
  • 时间复杂度: O ( l o g N ) O(logN) O(logN)
  • 空间复杂度: O ( 1 ) O(1) O(1)
  1. 获取堆顶元素
    最大堆 的堆顶元素是 堆 中的最大值,最小堆 的堆顶元素是 堆 中的最小值。因此,堆顶元素是 堆 中最重要的元素。
  • 时间复杂度: O ( 1 ) O(1) O(1)
  • 空间复杂度: O ( 1 ) O(1) O(1)
  1. 删除堆顶元素
    删除堆顶元素后,值得注意的是,堆 依旧需要维持它的特性。此时,新的堆顶元素也是当前堆中的最大值(如果堆是 最大堆)或最小值(如果堆是 最小堆)。
  • 时间复杂度: O ( l o g N ) O(log N) O(logN)
  • 空间复杂度: O ( 1 ) O(1) O(1)
  1. 获取堆的长度
    删除堆顶元素后,值得注意的是,堆 依旧需要维持它的特性。此时,新的堆顶元素也是当前堆中的最大值(如果堆是 最大堆)或最小值(如果堆是 最小堆)。
  • 时间复杂度: O ( l o g N ) O(log N) O(logN)
  • 空间复杂度: O ( 1 ) O(1) O(1)
  1. 获取堆的长度
    堆 的长度可以用来判断当前堆的大小,也可以用来判断当前堆是否还有元素。如果当前堆中没有元素,则 堆 的长度为 0。
  • 时间复杂度: O ( 1 ) O(1) O(1)
  • 空间复杂度: O ( 1 ) O(1) O(1)

在这里插入图片描述

# 最小堆完整代码
import heapq

# 新建一个列表
minHeap = []
# 将列表堆化,即将列表转换为最小堆
heapq.heapify(minHeap)
# 分别往最小堆中添加3,1,2
heapq.heappush(minHeap, 3)
heapq.heappush(minHeap, 1)
heapq.heappush(minHeap, 2)
# 查看最小堆的所有元素,结果为:[1,3,2]
print("minHeap: ",minHeap)
# 获取最小堆的堆顶元素
peekNum = minHeap[0]
# 结果为:1
print("peek number: ", peekNum)
# 删除最小堆的堆顶元素
popNum = heapq.heappop(minHeap)
# 结果为:1
print("pop number: ", popNum)
# 查看删除1后最小堆的堆顶元素,结果为:2
print("peek number: ", minHeap[0])
# 查看最小堆的所有元素,结果为:[2,3]
print("minHeap: ",minHeap)
# 获取堆的元素个数,即堆的长度
size = len(minHeap)
# 结果为:2
print("minHeap size: ", size)

3.堆的应用

1.排序

思路:堆排序指的是利用堆的数据结构对一组无序元素进行排序。
最小堆排序算法步骤如下:

  1. 将所有元素堆化成一个最小堆;
  2. 去除并删除堆顶元素,并将堆顶元素放置在存储有序元素的数据集T中。
  3. 此时,堆会调整成新的最小堆。
  4. 重复3和4步骤,直到堆中没有元素;
  5. 此时得到一个新的数据集T,其中的元素按照从小到大的顺序排列。

最大堆的排序算法步骤如下:(其实可以利用最小堆来实现)

  1. 将所有元素堆化成一个 最大堆;
  2. 取出并删除堆顶元素,并将该堆顶元素放置在存储有序元素的数据集 T 中;
  3. 此时,堆 会调整成新的 最大堆;
  4. 重复 3 和 4 步骤,直到 堆 中没有元素;
  5. 此时得到一个新的数据集 T,其中的元素按照从大到小的顺序排列
    时间复杂度: O ( N l o g N ) O(Nlog N) O(NlogN) N N N是 堆 中的元素个数。(每次获取一个最大/最小元素都需要logN的时间)
    空间复杂度: O ( N ) O(N) O(N) N N N是 堆 中的元素个数。

2.Top K问题

1.解法1

思路:主要是利用堆的数据结构获取最大元素或者最小元素
【Top k小元素】解法步骤:

  1. 创建一个【最小堆】
  2. 将所有元素都加到【最小堆】中
  3. 通过【边删除边遍历】的方法,将堆顶元素删除,并将它保存到结果集T中
  4. 重复3步骤K次,直到去除前K个最小的元素。
    时间复杂度: O ( K l o g N ) O(KlogN) O(KlogN)
    空间复杂度: O ( N ) O(N) O(N),(堆的大小)
2.解法2(常用)

利用最大堆来获取最小的top k个元素。
【Top k 小元素】解法步骤:

  1. 创建一个大小为K的 【最大堆】
  2. 依次将元素添加到 【最大堆】
  3. 【最大堆】 的元素个数达到k时,将当前元素与堆顶元素进行对比;
    如果当前元素 大于堆顶元素,则放弃当前元素,继续进行下一个元素;
    如果当前元素 小于堆顶元素,则删除堆顶元素,将当前元素加入到【最小堆】中。
  4. 重复步骤2和步骤3,直到所有元素遍历完毕
  5. 此时【最大堆】中的k个元素就是前K个最小的元素。
    时间复杂度: O ( N l o g K ) O(NlogK) O(NlogK)
    空间复杂度: O ( K ) O(K) O(K),(堆的大小)

3.Top Kth问题

1.解法1(常用)

Top kth 大元素解法步骤:

  1. 创建一个大小为k的【最小堆】
  2. 一次将元素进行添加到【最小堆】中,
  3. 当【最小堆】的元素个数达到k时,将当前元素与堆顶元素进行比较:
    如果当前元素小于堆顶元素,则放弃当前元素,继续进行下一个元素;
    如果当前元素大于堆顶元素,则删除堆顶元素,将单签元素加入到【最小堆】中。
  4. 重复步骤2和步骤3,直到所有元素遍历完成。
  5. 此时【最小堆】中的堆顶元素就是第K个最大的元素。
    时间复杂度: O ( N l o g K ) O(NlogK) O(NlogK)
    空间复杂度: O ( K ) O(K) O(K),(堆的大小)
2.解法2

Top kth 大元素解法步骤:

  1. 创建一个「最大堆」;
  2. 将所有元素都加到「最大堆」中;
  3. 通过 「边删除边遍历」(大部分语言中为 pop() 或者 poll()) 方法,将堆顶元素删除;
  4. 重复 3 步骤 K 次,直到获取到第 K 个最大的元素;

时间复杂度: O ( K l o g N ) O(KlogN) O(KlogN)
空间复杂度: O ( N ) O(N) O(N),(堆的大小)

三、题

1.简单

剑指 Offer 40. 最小的k个数
输入整数数组 arr ,找出其中最小的 k 个数。例如,输入4、5、1、6、2、7、3、8这8个数字,则最小的4个数字是1、2、3、4。
示例 1:
输入:arr = [3,2,1], k = 2
输出:[1,2] 或者 [2,1]
示例 2:
输入:arr = [0,1,2,1], k = 1
输出:[0]

class Solution:
    def getLeastNumbers(self, arr: List[int], k: int) -> List[int]:
        # 思路1:排序,返回前k个数   时间:o(NlogN)   空间:o(Nlog N)
        # arr.sort()
        # return arr[:k]
        # 思路2:利用最小堆来实现  时间:o(klogN)   空间:o(N)
        ans=[]
        heapq.heapify(arr)
        for i in range(k):
            ans.append(heapq.heappop(arr))
        return ans

703. 数据流中的第 K 大元素
设计一个找到数据流中第 k 大元素的类(class)。注意是排序后的第 k 大元素,不是第 k 个不同的元素。

请实现 KthLargest 类:

KthLargest(int k, int[] nums) 使用整数 k 和整数流 nums 初始化对象。
int add(int val) 将 val 插入数据流 nums 后,返回当前数据流中第 k 大的元素。

示例:

输入:
[“KthLargest”, “add”, “add”, “add”, “add”, “add”]
[[3, [4, 5, 8, 2]], [3], [5], [10], [9], [4]]
输出:
[null, 4, 5, 5, 8, 8]

解释:
KthLargest kthLargest = new KthLargest(3, [4, 5, 8, 2]);
kthLargest.add(3); // return 4
kthLargest.add(5); // return 5
kthLargest.add(10); // return 5
kthLargest.add(9); // return 8
kthLargest.add(4); // return 8

class KthLargest:
	# 解法1
    def __init__(self, k: int, nums: List[int]):
        self.k=k
        self.num_copy=nums
        heapq.heapify(self.num_copy)
    def add(self, val: int) -> int:
        heapq.heappush(self.num_copy,val)
        while len(self.num_copy)>self.k:
            heapq.heappop(self.num_copy)
        return self.num_copy[0]

2. 中等

215. 数组中的第K个最大元素
给定整数数组 nums 和整数 k,请返回数组中第 k 个最大的元素。

请注意,你需要找的是数组排序后的第 k 个最大的元素,而不是第 k 个不同的元素。

示例 1:

输入: [3,2,1,5,6,4] 和 k = 2
输出: 5

class Solution:
    def findKthLargest(self, nums: List[int], k: int) -> int:
        # 思路1:排序
        # nums.sort()
        # return nums[-k]
        # 思路2:最大堆    
        nums=[-i for i in nums]
        heapq.heapify(nums)
        while k-1>0:          # 写1 的原因是获取第k个最大元素,则第k个是不必要删除的
            heapq.heappop(nums)
            k-=1
        return -nums[0]

3.高频top10

347. 前 K 个高频元素
给你一个整数数组 nums 和一个整数 k ,请你返回其中出现频率前 k 高的元素。你可以按 任意顺序 返回答案。
示例 1:
输入: nums = [1,1,1,2,2,3], k = 2
输出: [1,2]
示例 2:
输入: nums = [1], k = 1
输出: [1]

class Solution:
    def topKFrequent(self, nums: List[int], k: int) -> List[int]:
        # 思路1:哈希法,时间复杂度0(nlogn) 空间复杂度o(n)
        ans=[]
        dict_count=Counter(nums)
        dict_count=sorted(dict_count.items(),key=lambda x:x[1],reverse=True)
        for i in range(k):
            ans.append(dict_count[i][0])
        return ans
class Solution:
    def topKFrequent(self, nums: List[int], k: int) -> List[int]:
        # 思路2:哈希统计,然后利用最小堆进行获取频数最高的k个数   时间复杂度  o(nlogk)  空间复杂度o(k)
        ans=[]
        dict_count=Counter(nums)
        minheap=[]
        # 将元素进行传入到最小堆中(大小只为k),超过K每次去除最小次数的元素
        for key,val in dict_count.items():
            heapq.heappush(minheap,(val,key))       # 元祖形式传入,默认是以第一位进行构建最小堆
            if len(minheap)>k:
                heapq.heappop(minheap)
        # 取出前k个高频元素
        ans=[]
        for i in range(k):
            ans.append(heapq.heappop(minheap)[1])
        return ans

912. 排序数组
给你一个整数数组 nums,请你将该数组升序排列。

示例 1:

输入:nums = [5,2,3,1]
输出:[1,2,3,5]
示例 2:

输入:nums = [5,1,1,2,0,0]
输出:[0,0,1,1,2,5]

class Solution:
    def sortArray(self, nums: List[int]) -> List[int]:
        # nums.sort()
        # return nums
        # 思路:堆排序    时间复杂度  o(n log n)  空间复杂度 o(n)
        ans=[]
        heapq.heapify(nums)
        while len(nums)>0:
            ans.append(heapq.heappop(nums))
        return ans

面试题 17.14. 最小K个数
设计一个算法,找出数组中最小的k个数。以任意顺序返回这k个数均可。

示例:

输入: arr = [1,3,5,7,2,4,6,8], k = 4
输出: [1,2,3,4]

class Solution:
    def smallestK(self, arr: List[int], k: int) -> List[int]:
        #思路1: top kth 问题(堆)  求k个最小数,可以转化成,用最大堆存储最小的k个数   时间复杂度o(nlogk) 空间复杂度o(k)
        ans=[]
        i=0
        while i<len(arr):
            heapq.heappush(ans,-arr[i])
            if len(ans)>k:
                heapq.heappop(ans)
            i+=1
        return [-i for i in ans]

23. 合并K个升序链表
给你一个链表数组,每个链表都已经按升序排列。

请你将所有链表合并到一个升序链表中,返回合并后的链表。
示例 1:

输入:lists = [[1,4,5],[1,3,4],[2,6]]
输出:[1,1,2,3,4,4,5,6]
解释:链表数组如下:
[
1->4->5,
1->3->4,
2->6
]
将它们合并到一个有序链表中得到。
1->1->2->3->4->4->5->6

# Definition for singly-linked list.
# class ListNode:
#     def __init__(self, val=0, next=None):
#         self.val = val
#         self.next = next
class Solution:
    def mergeKLists(self, lists: List[Optional[ListNode]]) -> Optional[ListNode]:
        #思路1:暴力,添加全部值,然后排序,最后生成链接  时间复杂度 o(n*k log n*k) 空间复杂度  o(n)
        ans=[]
        for head in lists:
            while head:
                ans.append(head.val)
                head=head.next
        ans.sort()
        head=ListNode(-1)
        curr=head
        for i in ans:
            curr.next=ListNode(i)
            curr=curr.next
        return head.next

        # 思路2: 利用最小堆 一直存储 lists中每个小list的最小值序列,然后依次添加  时间复杂度 o(n*k log k) 空间复杂度  o(k)  是k的原因在于,每一次只获取全部子链表中的最小值进行比较。
        ans=[]
        head=ListNode(-1)
        curr=head
        for i in range(len(lists)):
            if lists[i]:
                heapq.heappush(ans,(lists[i].val,i))    # 默认是对val进行最小堆的比较
                lists[i]=lists[i].next                  # 子链表第一个元素已经添加到最小堆中,则下一次都是从第二个元素开始   
        while ans:
            val,idx=heapq.heappop(ans)      # 返回最小堆的最小的元素
            curr.next=ListNode(val)         # 添加最小节点
            curr=curr.next
            if lists[idx]:                  # 如果子链表还存在元素,则进行添加
                heapq.heappush(ans,(lists[idx].val,idx))
                lists[idx]=lists[idx].next  #获取子链表的下一个元素
        return head.next

239. 滑动窗口最大值
给你一个整数数组 nums,有一个大小为 k 的滑动窗口从数组的最左侧移动到数组的最右侧。你只可以看到在滑动窗口内的 k 个数字。滑动窗口每次只向右移动一位。

返回 滑动窗口中的最大值 。

示例 1:

输入:nums = [1,3,-1,-3,5,3,6,7], k = 3
输出:[3,3,5,5,6,7]
解释:
滑动窗口的位置 最大值


[1 3 -1] -3 5 3 6 7 3
1 [3 -1 -3] 5 3 6 7 3
1 3 [-1 -3 5] 3 6 7 5
1 3 -1 [-3 5 3] 6 7 5
1 3 -1 -3 [5 3 6] 7 6
1 3 -1 -3 5 [3 6 7] 7

class Solution:
    def maxSlidingWindow(self, nums: List[int], k: int) -> List[int]:
        # 最大堆,只管添加,知道最大值的索引小于i-k时,开始删除(将堆中索引小于i-k的都删除)
        q=[(-nums[i],i) for i in range(k)]
        heapq.heapify(q)
        ans=[-q[0][0]]
        for i in range(k,len(nums)):
            heapq.heappush(q,(-nums[i],i))
            while q[0][1]<=i-k:         # 使用while原因在于  ,有可能子节点的索引也超过了当前的滑动窗口范围
                heapq.heappop(q)
            ans.append(-q[0][0])
        return ans

复杂度分析

  • 时间复杂度:O(nlogn),其中 n 是数组 nums 的长度。在最坏情况下,数组 nums 中的元素单调递增,那么最终优先队列中包含了所有元素,没有元素被移除。由于将一个元素放入优先队列的时间复杂度为 O(logn),因此总时间复杂度为 O(nlogn)。
  • 空间复杂度:O(n),即为优先队列需要使用的空间。这里所有的空间复杂度分析都不考虑返回的答案需要的 O(n) 空间,只计算额外的空间使用。

剑指 Offer II 061. 和最小的 k 个数对
给定两个以升序排列的整数数组 nums1 和 nums2 , 以及一个整数 k 。

定义一对值 (u,v),其中第一个元素来自 nums1,第二个元素来自 nums2 。

请找到和最小的 k 个数对 (u1,v1), (u2,v2) … (uk,vk) 。

示例 1:

输入: nums1 = [1,7,11], nums2 = [2,4,6], k = 3
输出: [1,2],[1,4],[1,6]
解释: 返回序列中的前 3 对数:
[1,2],[1,4],[1,6],[7,2],[7,4],[11,2],[7,6],[11,4],[11,6]

class Solution:
    def kSmallestPairs(self, nums1: List[int], nums2: List[int], k: int) -> List[List[int]]:
        # s
        # m, n = len(nums1), len(nums2)
        # ans = []
        # pq = [(nums1[i] + nums2[0], i, 0) for i in range(min(k, m))]
        # while pq and len(ans) < k:
        #     _, i, j = heappop(pq)
        #     ans.append([nums1[i], nums2[j]])
        #     if j + 1 < n:
        #         heappush(pq, (nums1[i] + nums2[j + 1], i, j + 1))
        # return ans
        # 和最小的k个数对,那么使用最大堆进行实现  时间复杂度为o(n^2logk)  空间复杂度为o(n)
        pq=[]
        for i in range(len(nums1)):
            for j in range(len(nums2)):
                heapq.heappush(pq,(-nums1[i]-nums2[j],i,j))
                if len(pq)>k:
                    heapq.heappop(pq)
        ans=[]
        for i in pq:
            ans.append([nums1[i[1]],nums2[i[2]]])
        return ans

264. 丑数 II
给你一个整数 n ,请你找出并返回第 n 个 丑数 。

丑数 就是只包含质因数 2、3 和/或 5 的正整数。

示例 1:

输入:n = 10
输出:12
解释:[1, 2, 3, 4, 5, 6, 8, 9, 10, 12] 是由前 10 个丑数组成的序列。

class Solution:
    def nthUglyNumber(self, n: int) -> int:
        # 丑数即是2,3,5的倍数
        factors = [2, 3, 5]
        seen = {1}
        heap = [1]
        for i in range(n - 1):
            curr = heapq.heappop(heap)
            for factor in factors:
                if (nxt := curr * factor) not in seen:
                    seen.add(nxt)
                    heapq.heappush(heap, nxt)
        return heap[0]


复杂度分析

  • 时间复杂度:O(nlogn)。得到第 n 个丑数需要进行 n 次循环,每次循环都要从最小堆中取出 1 个元素以及向最小堆中加入最多 3 个元素,因此每次循环的时间复杂度是 O(log3n+3log3n)=O(logn),总时间复杂度是 O(nlogn)。

  • 空间复杂度:O(n)。空间复杂度主要取决于最小堆和哈希集合的大小,最小堆和哈希集合的大小都不会超过 3n。

在这里插入图片描述基于LLM实现金融领域数据分析agent
原因:(1)由于输入LLMs上下文的限制,直接读取和处理大量数据与处理文本一样具有挑战性LLMs。此外,在直接访问私有数据源时LLMs,还存在数据泄露的潜在风险。(2)数据处理非常复杂,涉及许多繁琐的数值计算和错综复杂的表格操作。LLMs不擅长执行这些任务。(3)只能LLM输出文本,而我们在分析数据时通常更喜欢图表或表格。
第一步,数据探索,将将每个数据源转换成解析文件,包括数据说明、访问方法、数据架构(每列的名称)和用法示例,然后将解析文件和一些请求通过prompt书写的形式输入到讯飞星火max模型中,进行生成更多样化的请求。对得到的请求可能存在幻觉请求,因此通过生成好的请求,通过反向转换调用api的形式是否有关键信息和报错内容,从而过滤掉幻觉请求。
第二部,根据大量的请求通过LLM生成通过接口代码。操作时,将数据解析文件和现有接口作为prompt输入,让llm为每个请求生成一个完整的代码,生成过程中,优先使用现有接口,如果不满足则进行重新生成新的接口。然后进行不断的迭代。

数据探索,将每个数据源转换成解析文件并加上请求,通过讯飞星火max模型生成更多多样化请求。
在这里插入图片描述

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值