【优选算法】分治 {三分快排:三指针优化,随机选key,快速选择算法;归并排序:统计数组中的逆序对,统计数组中的翻转对;相关编程题解析}

news2024/11/17 17:47:27

一、经验总结

1.1 三分快排

优化一:三指针优化

之前学习的快速排序无法妥善处理相等或重复序列的排序问题(有序且三数取中无效),使快速排序的效率无法达到最优。

为了解决重复序列的问题,我们将原先的双指针法(前后指针)优化为三指针,将数组划分成三块:

  • [0, left]:< key
  • [left+1, right-1]:==key
  • [riight, n-1]:> key
  • 其中left标记<key区间的最右侧;i负责从左向右遍历数组;right标记>key区间的最左侧;

之后,再利用分治思想将<key和>key的部分进行排序即可,所有==key的部分已经移动到了最终的位置上。完美的解决了重复序列的问题。

举个极端一点的例子,对于全体重复的序列,原先需要partition n次,每次都要将区间遍历一遍是一个典型的复杂度为O(N^2)的算法。现在,仅需要partition一次就可以将所有数字归入==key的区间,不再有<key和>key的部分排序结束,复杂度降为O(N)。

优化二:随机选key

之前我们使用的是取最左(右)值为key、三数取中为key。实际上随机取key可以使数组划分的更为均匀,每个区间都是等概率划分的。使快速排序的时间复杂度更接近于O(NlogN)。

三分快排的应用:快速选择算法

快速选择算法是解决Topk问题的最优方案,之前学习过的利用堆解决Topk问题时间复杂度为O(NlogK),已经相当高效了。但是快速选择算法可以将时间复杂度优化为O(N)。

快速选择算法的原理是基于三分快排的,但并不需要将数组完全排序,而是将数组划分为三块以后,将三块区间内元素的个数与k比较,再进行递归分割,直到将最小(最大)的前k个数全部移动到数组前面(后面)。

Topk问题又分前k小(大)、第k小(大)。前k小只需要将最小的前k个数全部移动到数组前面即可,<key区间内的元素个数只要==k就可以返回。而第k小不仅要移动最小的前k个数,还必须找到第k个,即第k个数必须刚好落在==key的区间内才能返回。


1.2 归并排序

利用归并排序统计数组中的逆序对

所谓逆序对是指前大后小的一对数,利用归并排序统计逆序对可以将暴力解法的时间复杂度O(N^2),优化为O(NlogN)。算法思路如下:

  1. 将数组从中间一分为二,先统计左右区间内的逆序对,并进行排序。
  2. 然后再归并左右区间的过程中,统计一左一右跨两个区间的逆序对,有两个策略可供选择
    1. 升序排序:以右区间中的元素cur2为基点,在左区间中找大于cur2的元素cur1,因为是升序所以左区间之后的元素都大。
    2. 降序排序:以左区间中的元素cur1为基点,在右区间中找小于cur1的元素cur2,因为是降序所以右区间之后的元素都小
  3. 颠来倒去其实都是在cur1 > cur2的时候,统计逆序对的数量,只是基点不同:先左后右是降序,先右后左是升序
  4. 逆序对的判定规则与左右区间归并的比较规则相同,所以可以在左右区间归并的过程中顺道统计逆序对的个数。

利用归并排序统计数组中的翻转对

不同于逆序对,翻转对要求前一个数大于后一个数的两倍。翻转对的判定规则与左右区间归并的比较规则不同,也就不能顺道了。但是翻转对的判定与统计仍然可以利用归并排序的分治和左右区间有序的条件,只是需要在左右区间归并之前,先一步进行一左一右的翻转对统计即可。

在统计一左一右跨两个区间的翻转对时,算法规律和逆序对相同:在cur1/2 > cur2(乘法改除法防溢出)的时候,统计翻转对的数量。先左后右是降序,先右后左是升序。算法还可以使用同向双指针进行优化,只需要将左右两个区间遍历一遍O(N),就可以完成统计。不会影响整体归并排序的复杂度O(NlogN)。


二、相关编程题

2.1 三分快排

2.1.1 颜色分类

题目链接

75. 颜色分类 - 力扣(LeetCode)

题目描述

在这里插入图片描述

算法原理

在这里插入图片描述

编写代码

class Solution {
public:
    void sortColors(vector<int>& nums) {
        int n = nums.size();
        int left = -1, i = 0, right = n;
        while (i < right) {
            if (nums[i] == 0) {
                if (++left != i)
                    swap(nums[left], nums[i]);
                ++i;
            } else if (nums[i] == 1) {
                ++i;
            } else if (nums[i] == 2 && --right != i) {
                swap(nums[i], nums[right]);
            }
        }
    }
};

2.1.2 优化快速排序

题目链接

912. 排序数组 - 力扣(LeetCode)

题目描述

在这里插入图片描述

算法原理

在这里插入图片描述

编写代码

class Solution {
public:
    vector<int> sortArray(vector<int>& nums) {
        srand(time(nullptr));
        QuickSort(nums, 0, nums.size()); //注意区间是左闭右开
        return nums;
    }

    void QuickSort(vector<int>& nums, int begin, int end)
    {
        if(end - begin < 2) return;
        int key = nums[rand()%(end-begin)+begin]; //随机取key
        int left = begin-1, i = begin, right = end;
        while(i < right)
        {
            if(nums[i] < key)   swap(nums[++left], nums[i++]);
            else if(nums[i] == key) ++i;
            else swap(nums[--right], nums[i]);
        }
        //left和right都是闭端点
        QuickSort(nums, begin, left+1); //left做end需要+1(右开)
        QuickSort(nums, right, end); //right做begin不需要+1(左闭)
    }
};

2.1.3 数组中的第k个最大元素

题目链接

215. 数组中的第K个最大元素 - 力扣(LeetCode)

题目描述

在这里插入图片描述

算法原理

在这里插入图片描述

编写代码

//快速选择算法 O(N)
class Solution {
public:
    int findKthLargest(vector<int>& nums, int k) {
        srand(time(nullptr));
        return QuickSelect(nums, 0, nums.size()-1, k); //注意区间是左闭右闭
    }

    int QuickSelect(vector<int>& nums, int begin, int end, int k)
    {
        // 当区间内只有一个元素时,直接返回这个元素
        if(begin == end) return nums[begin];
        // 随机选key
        int key = nums[rand()%(end-begin+1)+begin]; 
        // 将区间内的元素划分成三块
        int left = begin-1, i = begin, right = end+1;
        while(i < right)
        {
            if(nums[i] < key) swap(nums[++left], nums[i++]);
            else if(nums[i] == key) ++i;
            else swap(nums[--right], nums[i]);
        }
        //核心逻辑
        if(end-right+1 >= k) //c>=k
            return QuickSelect(nums, right, end, k); 
        else if(end-left >= k) //b+c>=k
            return key;
        else    
            return QuickSelect(nums, begin, left, k-(end-left)); //找k-b-c大的数
    }
};

//堆算法 O(NlogK)
class Solution {
public:K
    int findKthLargest(vector<int>& nums, int k) {
        vector<int> leastHeap(k);
        for(int i = 0; i < k; ++i)
        {
            leastHeap[i] = nums[i];
        }

        for(int i = k-2/2; i >= 0; --i)
        {
            AdjustDown(leastHeap, i);
        }

        for(int i = k; i < nums.size(); ++i)
        {
            if(nums[i] > leastHeap[0]) 
            {
                leastHeap[0] = nums[i];
                AdjustDown(leastHeap, 0);
            }
        }

        return leastHeap[0];
    }

    void AdjustDown(vector<int>& nums, int root) {
        int parent = root;
        int child = parent * 2 + 1;
        int n = nums.size();
        while (child < n) {
            if (child + 1 < n && nums[child + 1] < nums[child]) {
                ++child;
            }
            if (nums[child] < nums[parent]) {
                swap(nums[child], nums[parent]);
                parent = child;
                child = parent * 2 + 1;
            } else {
                break;
            }
        }
    }
};

2.1.4 最小的k个数

题目链接

LCR 159. 库存管理 III - 力扣(LeetCode)

题目描述

在这里插入图片描述

算法原理

在这里插入图片描述

编写代码

class Solution {
public:
    vector<int> inventoryManagement(vector<int>& stock, int cnt) {
        srand(time(nullptr));
        if(cnt > 0)
        	QuickSelect(stock, 0, stock.size()-1, cnt);
        return vector<int> (stock.begin(), stock.begin()+cnt);
    }

    void QuickSelect(vector<int>& nums, int begin, int end, int k)
    {
        // 当区间内只有一个元素时,直接返回
        if(begin == end) return;
        // 随机选key
        int key = nums[rand()%(end-begin+1)+begin]; 
        // 将区间内的元素划分成三块
        int left = begin-1, i = begin, right = end+1;
        while(i < right)
        {
            if(nums[i] < key) swap(nums[++left], nums[i++]);
            else if(nums[i] == key) ++i;
            else swap(nums[--right], nums[i]);
        }
        //核心逻辑
        if(left-begin+1 > k) //a>k
            QuickSelect(nums, begin, left, k); 
        else if(right-begin >= k) //a+b>=k
            return;
        else    
            QuickSelect(nums, right, end, k-(right-begin)); 
    }
};

2.2 归并排序

2.2.1 归并排序

题目链接

912. 排序数组 - 力扣(LeetCode)

题目描述

在这里插入图片描述

算法原理

在这里插入图片描述

编写代码

class Solution {
public:
    vector<int> sortArray(vector<int>& nums) {
        vector<int> tmp(nums.size()); //辅助数组在递归外创建效率更高
        MergeSort(nums, 0, nums.size(), tmp);
        return nums;
    }

    void MergeSort(vector<int>& nums, int begin, int end, vector<int>& tmp)
    {
        if(end-begin < 2) return;
        int begin1 = begin;
        int end1 = begin+(end-begin)/2;
        int begin2 = end1;
        int end2 = end;
        MergeSort(nums, begin1, end1, tmp);
        MergeSort(nums, begin2, end2, tmp);
        //归并左右两顺序区间
        int i = begin;
        while(begin1 < end1 && begin2 < end2)
        {
            if(nums[begin1] <= nums[begin2])
            {
                tmp[i++] = nums[begin1++];
            }
            else
            {
                tmp[i++] = nums[begin2++];
            }
        }
        while(begin1 < end1)
        {
            tmp[i++] = nums[begin1++];
        }
        while(begin2 < end2)
        {
            tmp[i++] = nums[begin2++];
        }
		
        for(int i = begin; i < end; ++i)
        {
            nums[i] = tmp[i];
        }
    }
};

2.2.2 数组中的逆序对

题目链接

LCR 170. 交易逆序对的总数 - 力扣(LeetCode)

题目描述

在这里插入图片描述

算法原理

在这里插入图片描述

编写代码

class Solution {
public:
    int reversePairs(vector<int>& record) {
        vector<int> tmp(record.size());
        return MergeSort(record, 0, record.size(), tmp);
    }
    
    int MergeSort(vector<int>& nums, int begin, int end, vector<int>& tmp)
    {
        //如果区间内的元素个数小于2,返回0个逆序对
        if(end-begin < 2) return 0;
        //将区间从中间划分成左右两个区间
        int begin1 = begin;
        int end1 = begin+(end-begin)/2;
        int begin2 = end1;
        int end2 = end;
        int cnt = 0;
		//左区间的个数+排序;右区间的个数+排序
        cnt += MergeSort(nums, begin1, end1, tmp);
        cnt += MergeSort(nums, begin2, end2, tmp);
		//一左一右的个数+归并排序
		//策略一:以cur2为基点,在之前找大
        int i = begin;
        while(begin1 < end1 && begin2 < end2)
        {
            if(nums[begin1] <= nums[begin2])
            {
                tmp[i++] = nums[begin1++];
            }
            else
            {
                cnt += end1-begin1;
                tmp[i++] = nums[begin2++];
            }
        }
        //策略二:以cur1为基点在之后找小
        // while(begin1 < end1 && begin2 < end2)
        // {
        //     if(nums[begin1] > nums[begin2])
        //     {
        //         cnt += end2 - begin2;
        //         tmp[i++] = nums[begin1++];
        //     }
        //     else
        //     {
        //         tmp[i++] = nums[begin2++];
        //     }
        // }
        while(begin1 < end1)
        {
            tmp[i++] = nums[begin1++];
        }
        while(begin2 < end2)
        {
            tmp[i++] = nums[begin2++];
        }
		//将归并排序好的区间元素拷贝回原数组
        for(int i = begin; i < end; ++i)
        {
            nums[i] = tmp[i];
        }
        return cnt; //返回的就是区间内的逆序对总数
    }
};

2.2.3 计算右侧小于当前元素的个数

题目链接

315. 计算右侧小于当前元素的个数 - 力扣(LeetCode)

题目描述

在这里插入图片描述

算法原理

在这里插入图片描述

编写代码

class Solution {
    vector<int> tmp1, tmp2;
public:
    vector<int> countSmaller(vector<int>& nums) {
        tmp1.resize(nums.size()); //用于归并排序nums
        tmp2.resize(nums.size()); //用于归并index,并不是排序,只是执行和nums同样的操作
        vector<int> ret(nums.size(), 0); //结果数组
        vector<int> index(nums.size()); //用于映射每个元素的原始下标
        for(int i = 0; i < nums.size(); ++i)
        {
            index[i] = i;
        }
        MergeSort(nums, 0, nums.size(), ret, index);
        return ret;
    }

    void MergeSort(vector<int>& nums, int begin, int end, vector<int>& ret, vector<int>& index)
    {
        if(end - begin < 2) return;
		//将数组从中间分成两个区间
        int begin1 = begin;
        int end1 = begin1+(end-begin)/2;
        int begin2 = end1;
        int end2 = end;
		//先分别处理左右区间内的个数
        MergeSort(nums, begin1, end1, ret, index);
        MergeSort(nums, begin2, end2, ret, index);
		//再处理一左一右的个数
        int i = begin;
        while(begin1 < end1 && begin2 < end2)
        {
            if(nums[begin1] > nums[begin2]) //降序排序
            {
                ret[index[begin1]] += end2-begin2; //注意:1.获取元素的原始下标 2.+=可能在左右区间中已经统计过了
                tmp1[i] = nums[begin1];
                tmp2[i++] = index[begin1++]; //nums数组中的元素移动到哪,index数组中的原始下标就移动到哪
            }
            else
            {
                tmp1[i] = nums[begin2];
                tmp2[i++] = index[begin2++];
            }
        }

        while(begin1 < end1)
        {
            tmp1[i] = nums[begin1];
            tmp2[i++] = index[begin1++];
        }

        while(begin2 < end2)
        {
            tmp1[i] = nums[begin2];
            tmp2[i++] = index[begin2++];
        }

        for(int i = begin; i < end; ++i)
        {
            nums[i] = tmp1[i];
            index[i] = tmp2[i];
        }

    }
};

2.2.4 翻转对

题目链接

493. 翻转对 - 力扣(LeetCode)

题目描述

在这里插入图片描述

算法原理

在这里插入图片描述

编写代码

class Solution {
    vector<int> tmp;
public:
    int reversePairs(vector<int>& nums) {
        int n = nums.size();
        tmp.resize(n);
        return MergeSort(nums, 0, n);
    }   

    int MergeSort(vector<int>& nums, int begin, int end)
    {
        if(end-begin < 2) return 0;
		//将数组从中间划分成左右两个区间
        int begin1 = begin;
        int end1 = begin1+(end-begin)/2;
        int begin2 = end1;
        int end2 = end;
        int cnt = 0;
        //分别去左右区间统计翻转对并进行排序
        cnt += MergeSort(nums, begin1, end1);
        cnt += MergeSort(nums, begin2, end2);
		//统计一左一右跨两个区间的翻转对
        int cur1 = begin1, cur2 = begin2;
        while(cur1 < end1 && cur2 < end2)
        {
            //策略一:在cur1后面找*2都比它小的数
            if(nums[cur1]/2.0 > nums[cur2]) //乘法改除法,防溢出
            {
                cnt += end2-cur2; //由于是降序,所以之后的都小
                ++cur1;
            }
            else
                ++cur2;
            //策略二:在cur2前面找/2都比它大的数
            // if(nums[cur1]/2.0 > nums[cur2])
            // {
            //     cnt += end1-cur1; //由于是升序,所以之后的都大
            //     ++cur2;
            // }
            // else
            //     ++cur1;
        }

        int i = begin;
        while(begin1 < end1 && begin2 < end2)
        {
            //降序排序
            if(nums[begin1] >= nums[begin2])
            {
                tmp[i++] = nums[begin1++];
            }
            else
            {
                tmp[i++] = nums[begin2++];
            }
            //升序排序
            // if(nums[begin1] <= nums[begin2])
            // {
            //     tmp[i++] = nums[begin1++];
            // }
            // else
            // {
            //     tmp[i++] = nums[begin2++];
            // }
        }

        while(begin1 < end1)
        {
            tmp[i++] = nums[begin1++];
        }
        while(begin2 < end2)
        {
            tmp[i++] = nums[begin2++];
        }

        for(int i = begin; i < end; ++i)
        {
            nums[i] = tmp[i];
        }
        return cnt;
    }
};

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1713532.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

Spire.PDF for .NET【文档操作】演示:将PDF 拆分为多个 PDF

Spire.PDF 完美支持将多页 PDF 拆分为单页。但是&#xff0c;更常见的情况是&#xff0c;您可能希望提取选定的页面范围并保存为新的 PDF 文档。在本文中&#xff0c;您将学习如何通过 Spire.PDF 在 C#、VB.NET 中根据页面范围拆分 PDF 文件。 Spire.PDF for .NET 是一款独立 …

光速进化!易天万兆光模块全面升级

易天光通信宣布10G SFP/25G SFP28系列光模块产品进行了全新升级&#xff0c;旨在为客户提供更优质、更高效、更可靠的光通信解决方案。这次升级不仅是技术的突破&#xff0c;更是对未来光通信发展趋势的深刻洞察和精准把握。 一、技术革新&#xff0c;性能卓越 本次全系列产品…

记一次艰难的SQL注入(过安全狗)

1.前言 最近在挖补天的src&#xff0c;然后挖出了不少SQL注入&#xff0c;完了出了数据库名就不管那么多提交了。今天挖了个报错注入的&#xff0c;突然一激灵&#xff0c;说我不能这样颓废下去了&#xff0c;刚好是个后台登录的界面&#xff0c;我决心要登进它的后台。 2.注入…

【UnityShader入门精要学习笔记】第十五章 使用噪声

本系列为作者学习UnityShader入门精要而作的笔记&#xff0c;内容将包括&#xff1a; 书本中句子照抄 个人批注项目源码一堆新手会犯的错误潜在的太监断更&#xff0c;有始无终 我的GitHub仓库 总之适用于同样开始学习Shader的同学们进行有取舍的参考。 文章目录 使用噪声上…

WebGL实现医学教学软件

使用WebGL实现医学教学软件是一个复杂但非常有益的项目&#xff0c;可以显著提升医学教育的互动性和效果。以下是详细的实现步骤&#xff0c;包括需求分析、技术选型、开发流程和注意事项。北京木奇移动技术有限公司&#xff0c;专业的软件外包开发公司&#xff0c;欢迎交流合作…

XV7011BB可为智能割草机的导航系统提供新的解决方案

智能割草机作为现代家庭和商业草坪维护保养的重要工具&#xff0c;其精确的定位和导航系统对于提高机器工作效率和确保安全运行至关重要。在智能割草机的发展历程中&#xff0c;定位和导航技术一直是关键的创新点。 传统的基于RTK(实时动态差分定位技术)技术的割草机虽然在…

对比方案:5款知识中台工具的优缺点详解

知识中台工具为企业和组织高效地组织、存储和分享知识&#xff0c;还能提升团队协作的效率。在选择搭建知识中台的工具时&#xff0c;了解工具的优缺点&#xff0c;有助于企业做出最佳决策。本文LookLook同学将对五款搭建知识中台的工具进行优缺点的简单介绍&#xff0c;帮助企…

wifi贴码推广哪家靠谱?

如今越来越多的人想轻资产创业&#xff0c;WIFI贴码是共享行业最无成本的创业项目了&#xff0c;而在选择厂商的时候&#xff0c;大家就想要知道哪家公司靠谱&#xff0c;更好、更便宜、可靠。那么wifi贴码推广哪家靠谱&#xff1f;别急&#xff0c;下面小编将带你一起了解。 目…

分享 - 树形dp

树形 d p dp dp 例1 - 基础 链接&#xff1a;树上子链 练手 分析 其实一看题就很显然的树形 d p dp dp子链在这里分为两种情况&#xff0c;如图黑链和红链 思路 d p [ i ] dp[i] dp[i] 表示以 i i i 开头的红链的最大权值易得&#xff1a; d p [ i ] m a x ( d p [ i…

游泳时用什么耳机听歌好?精品榜前四游泳耳机揭秘,款款佳品!

游泳时用什么耳机听歌好&#xff1f;这无疑是众多水上运动爱好者的共同疑问。在享受游泳带来的清凉与畅快时&#xff0c;若能伴随着悦耳的音乐&#xff0c;无疑能让整个体验更加完美。然而&#xff0c;市面上的游泳耳机种类繁多&#xff0c;品质各异&#xff0c;如何选择一款既…

乐鑫ESP串口驱动安装,安装cp210x驱动

windows11安装cp210x驱动&#xff1a; 1&#xff1a;第一步官网下载驱动&#xff1a; 官网地址如下&#xff1a; CP210x USB to UART Bridge VCP Drivers - Silicon Labs 第二步&#xff1a;解压文件夹并安装如图所示&#xff1a; 3&#xff1a;第三步安装成功后会给你个提示…

一个小技巧轻松提升量化精度!IntactKV:保持关键词元无损的大语言模型量化方法

目录 摘要关键词元&#xff08;Pivot Tokens&#xff09;方法概述实验验证1. 权重量化2. KV Cache 量化3. 权重和激活值量化 参考文献 本文介绍我们针对大语言模型量化的工作 IntactKV&#xff0c;可以作为插件有效提升 GPTQ、AWQ、QuaRot 等现有主流量化方法效果。论文作者来自…

CPU对代码执行效率的优化,CPU的缓存、指令重排序

目录 一、CPU对代码执行效率的优化 1. 指令流水线&#xff08;Instruction Pipelining&#xff09; 2. 超标量架构&#xff08;Superscalar Architecture&#xff09; 3. 动态指令重排序&#xff08;Dynamic Instruction Reordering&#xff09; 4. 分支预测&#xff08;…

visio中画乘法器加法器符号

情景&#xff1a;在进行rtl设计时&#xff0c;需要画出简单的电路实现图&#xff0c;需要用到加法器&#xff0c;乘法器的符号。 位置&#xff1a;在visio的更多形状中&#xff0c;找到如下图的位置&#xff0c;进行添加&#xff0c;即可 最终效果&#xff1a; 可以满足我们日…

基于L1范数惩罚的稀疏正则化最小二乘心电信号降噪方法(Matlab R2021B)

L1范数正则化方法与Tikhonov正则化方法的最大差异在于采用L1范数正则化通常会得到一个稀疏向量&#xff0c;它的非零系数相对较少&#xff0c;而Tikhonov正则化方法的解通常具有所有的非零系数。即&#xff1a;L2范数正则化方法的解通常是非稀疏的&#xff0c;并且解的结果在一…

虹科Pico汽车示波器 | 免拆诊断案例 | 2010 款北京现代ix35车挡位偶尔锁定在4挡

故障现象 一辆2010款北京现代ix35车&#xff0c;搭载G4KD发动机和6速自动变速器&#xff0c;累计行驶里程约为23.6万km。该车行驶中急加速时&#xff0c;挡位偶尔锁定在4挡&#xff0c;同时发动机故障灯异常点亮。 故障诊断 该车自动变速器控制模块&#xff08;TCM&#xff0…

css-calc动态计算属性值无效

1.calc计算 可以使用css属性动态适应盒子的宽高&#xff0c;适用于布局中左侧固定宽或高&#xff0c;右侧宽度适应&#xff1b;右侧宽度等于calc(100vw - rightWidth); 2.属性值无效 3.解决 width: calc(100vw - 360px); 减号左右需要空格

Kivy 项目51斩百词 5

MRWord\pages\infopage\info.py def read_random_word(self) def read_random_word(self):"""随机读取一条数据"""sql "SELECT * FROM word WHERE id (SELECT word_id FROM today ORDER BY RANDOM() limit 1)"rows select_data(sq…

Google使用AI改进了 Sheets;开源视觉语言模型llama3v;开源情绪语音模型ChatTTS;

✨ 1: Google has improved Sheets with AI. Google 使用 AI 改进了 Sheets 您可以使用 Gemini 处理您的数据并将其变成老师。 优化您的数据 Gemini 了解您的数据并提出改进建议。 例如&#xff0c;它可以将重复数据转换为更实用的下拉框。 解释数据 通过单击双子座图标…

产品推荐 | 基于Xilinx Zynq-7015 FPGA的MYC-C7Z015开发板

一、产品概述 基于 Xilinx Zynq-7015&#xff0c;双Cortex-A9FPGA全可编程处理器&#xff1b;PS部分(ARM)与PL部分(FPGA)之间采用AXI高速片上总线通信&#xff0c;吉比特级带宽&#xff0c;突破传统ARMFPGA架构的通信瓶颈&#xff0c;通过PL部分(FPGA)灵活配置丰富的外设接口&…