【初阶数据结构与算法】沉浸式刷题之顺序表练习(顺序表以及双指针两种方法)

news2024/11/8 1:44:31

在这里插入图片描述

文章目录

  • 顺序表练习
    • 1.移除数组中指定的元素
      • 方法1(顺序表)
      • 方法2(双指针)
    • 2.删除有序数组中的重复项
      • 方法1(顺序表)
      • 方法2(双指针)
    • 3.双指针练习之合并两个有序数组
      • 方法1(直接排序)
      • 方法2(双指针)

顺序表练习

   在顺序表练习中我们会首先使用我们学过的顺序表来解决,然后再同时介绍一下其它方法,在练习开始之前我们要说明一个东西,就是我们之前不是写好了一个顺序表吗?我们等一下就直接全部复制过来用
   那么是不是就说明我们以后要用数据结构做题就必须把它手写一遍吗?这是不需要的,后面我们会介绍C++,在C++中的STL中有现成的可以用,现在我们还没有介绍到,就复制我们写过的数据结构来做题
   在做题过程中,我们也会计算这些方法的时间复杂度和空间复杂度,也是对之前内容的一个复习

1.移除数组中指定的元素

题目链接:https://leetcode.cn/problems/remove-element/description/

方法1(顺序表)

   我们先来看看题目描述:
在这里插入图片描述
   题目中的第一个用例:
在这里插入图片描述
   题目给出的函数模型:
在这里插入图片描述
   根据上面的图片描述,我们基本明确了题意,就是给我们一个数组和一个值,然后把数组中和这个值相等的元素移除掉,最后返回处理后的数组中的有效元素个数
   方法1的思路就是直接使用我们的顺序表,在顺序表中我们提供了查找方法,并且提供了删除指定位置元素的方法,我们就可以在顺序表中查找要删除的元素,然后把返回来的下标作为参数传给删除函数
   首先我们把写过的顺序表拷贝到题目中,在使用顺序表之前,我们要创建一个顺序表,并且使用初始化方法对它初始化,为了防止忘记销毁顺序表,我们可以先把顺序表的销毁也一起配套写上
   随后把数组中的内容尾插到我们的顺序表,我们才能使用顺序表对数据进行操作,如下:

int removeElement(int* nums, int numsSize, int val) 
{
    int i = 0;
    SL sl;
    SLInit(&sl);
    for(i = 0; i<numsSize; i++)
    {
        SLPushBack(&sl,nums[i]);
    }

    SLDestroy(&sl);
}

   随后我们就设计一个循环,让它能够一直找题目给出的元素,然后每找到一个就调用删除方法把它删除,那么循环的结束条件是什么呢?我们可以根据查找方法的返回值来设计,如果没有在顺序表中找到对应的元素会返回-1
   那么我们就判断它的返回值是否是-1,如果不是就进入循环将对应的元素删除,是的话就结束循环,如下:

while(SLFind(&sl,val) != -1)
{
    int ret = SLFind(&sl,val)
    SLErase(&sl,ret);
}

   处理完毕之后我们就把顺序表中的内容重新放入原数组,并且将数组有效元素个数记录下来,完整代码如下:

int removeElement(int* nums, int numsSize, int val) 
{
    int i = 0;
    SL sl;
    SLInit(&sl);
    for(i = 0; i<numsSize; i++)
    {
        SLPushBack(&sl,nums[i]);
    }
    while(SLFind(&sl,val) != -1)
    {
        int ret = SLFind(&sl,val);
        SLErase(&sl,ret);
    }
    for(i = 0; i<sl.size; i++)
    {
        nums[i] = sl.arr[i];
    }
    int k = sl.size;
    SLDestroy(&sl);
    return k;
}

   我们看看提交的结果:
在这里插入图片描述
   可以看到最后通过了,我们来分析一下代码的时间复杂度和空间复杂度,第一个和第二个for循环都是O(N),关键在于第二个while循环的时间复杂度
   由于我们的查找方法和删除方法时间复杂度都是O(N),外层有一个while循环,所以时间复杂度就是O(N^2),不是很好的一个时间
   接着来看空间复杂度,我们为了在顺序表中操作数组的数据,所以把数组中的数组全部放入了顺序表,所以顺序表会额外开辟数组元素大小的空间,空间复杂度为O(N)
   我们知道这个时间复杂度和空间复杂度都不是很好,所以我们要接着介绍另一个方法

方法2(双指针)

   这里的双指针不是创建两个指针变量,而是指数组中的下标,因为在数组中我们能够通过下标找到对应的元素,与指针很像,所以叫双指针
   具体方法就是创建两个整型变量src和dest,这两个名字在我们指针章节出现得不少,src代表源,dest代表目的地
   在双指针算法中,我们的思路很简单,就是首先让src和dest都指向数组的第一个元素,随后我们就看src位置上的值是否是题目给出的val,如果是我们就直接让src往后走一步
   如果不是,我们就把src位置上的值赋给dest,随后让dest和src都往后走一步,接下来我们就演示一下第一个示例的推演,如图:
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
   有了上图的分析,我们就可以来实现一下代码了,首先创建两个整型变量src和dest作为我们的双指针,初始情况下让它们都为0
   随后创建一个循环,循环条件就是src<numsSize,因为src是数组中的下标,要保证它不能越界,接着我们就进行判断,如果src位置的值等于dest位置的值,那么直接让src++
   否则的话就是不等于,那么把src位置的值赋值到dest位置,随后让它们都++,如下:

while (src < numsSize)
{
    if (nums[src] == val)
    {
        src++;
    }
    else
    {
        nums[dest++] = nums[src++];
    }
}

   最后我们直接返回dest即可,完整代码如下:

int removeElement(int* nums, int numsSize, int val) 
{
    int src = 0;
    int dest = 0;
    while(src < numsSize)
    {
        if(nums[src] == val)
        {
            src++;
        }
        else
        {
            nums[dest++] = nums[src++];
        }
    }
    return dest;
}

   最后我们提交一下就通过了,在双指针方法中,我们只有一个循环,时间复杂度为O(N),申请的空间也是常数个,所以时间复杂度为O(1),可以看到比使用顺序表的方法简便多了,时间复杂度和空间复杂度都降低了一个档次
   这道题的双指针法的本质就是,碰到了指定的元素就不管,直接跳过,然后把不是指定的元素放在前面,简单地说就是一个在前面探路,一个在后面接收

2.删除有序数组中的重复项

题目链接:https://leetcode.cn/problems/remove-duplicates-from-sorted-array/description/

方法1(顺序表)

   在这个题目中,方法1我们还是使用顺序表来做,我们首先来看看题目描述:
在这里插入图片描述
题目的第一个示例:
在这里插入图片描述
题目给出的函数原型:
在这里插入图片描述
   根据上面图片的解释,我们大致明白了题目的要求,就是数组是相对有序的,然后我们要删除那些重复项,让数组里面的元素变得唯一,最后返回唯一的元素个数,至于其它位置的元素就不管了
   首先我们还是拷贝顺序表代码,以及创建、销毁顺序表,把数组中的数据尾插到顺序表中,上面讲过了,接着我们就来讲这道题不同的地方
   由于数组是相对有序的,所以相同的元素肯定是放在一起的,所以我们就可以写一个循环来判断前后两个元素是否相等,如果相等我们就删除当前的元素,每删除一个元素numsSize就减1,要特别注意的一个点是要保证下标的有效性,如下:

for (i = 0; i < numsSize; i++)
{
    if (i + 1 < numsSize && sl.arr[i] == sl.arr[i + 1])
    {
        SLErase(&sl, i);
        numsSize--;
    }
}

   但是如果我们去运行这段代码就会发现第二个示例会出错,如下:

[0,0,1,1,1,2,2,3,3,4]

   我们把这个示例放到VS中调试一下,如图:
在这里插入图片描述
   这个时候我们发现了问题,当i = 1时,将下标为1的元素删除了,所有后面的其它元素都往前挪动了一步,导致现在下标为1和2的元素又相等了
   但是本次循环结束了,下一次在循环中i要++变成了2,i+1变成了3,比较不了下标为1和2的元素了,也就导致了下标为1和2的元素相等没有处理,如果看不懂这里的分析也没有关系,自行调试一下就明白了
   那么怎么解决呢?其实也很简单,问题就出在删除一个相同元素后,其余元素都往前挪动了,但是循环结束了,i要++,就不会再比较移动后的i下标位置的元素和i+1下标的元素了
   所以我们为了能够让它删除元素后,多比较一次原本移动后的i下标位置的元素和i+1下标的元素,我们可以在删除一个元素后让i- -,这样处理后下次进入循环i的值就不会变化,代码如下:

for (i = 0; i < numsSize; i++)
{
    if (i + 1 < numsSize && sl.arr[i] == sl.arr[i + 1])
    {
        SLErase(&sl, i);
        numsSize--;
        i--;
    }
}

   当完成上面的步骤之后我们再把顺序表中的数据拷贝回原数组中,此时的numsSize就是有效的元素个数,完整代码如下:

int removeDuplicates(int* nums, int numsSize)
{
    SL sl;
    int i = 0;
    SLInit(&sl);
    for (i = 0; i < numsSize; i++)
    {
        SLPushBack(&sl, nums[i]);
    }
    for (i = 0; i < numsSize; i++)
    {
        if (i + 1 < numsSize && sl.arr[i] == sl.arr[i + 1])
        {
            SLErase(&sl, i);
            numsSize--;
            i--;
        }
    }
    for (i = 0; i < numsSize; i++)
    {
        nums[i] = sl.arr[i];
    }
    SLDestroy(&sl);
    return numsSize;
}

   最后我们提交一下就可以通过了,在这个方法中,我们的时间复杂度也是很高的,达到了O(N^2),并且由于使用顺序表拷贝了原数组中的内容,空间复杂度也不低,达到了O(N),所以我们接下来介绍一个更好的方法

方法2(双指针)

   这道题还是可以使用我们的双指针法来做,上一题的双指针法的本质就是,碰到了指定的元素就不管,直接跳过,然后把不是指定的元素放在前面,本质就是一个在前面探路,一个在后面接收
   这道题也可以借鉴这样的思想,我们题目要求去掉相对有序的数组中的元素,说明相等的元素都是挨在一起的,我们还是可以定义两个变量src和dest,src在前面探路,dest在后面接收
   具体思路就是:初始情况下让dest指向第一个元素,而src指向第二个元素,因为如果它们都指向第一个元素,那么它们肯定就相等了,没有比较的必要,所以让src走到第二个元素的位置上
   然后我们就比较src和dest位置上的元素是否相等,如果相等我们就让让src++,其它什么都不做,如果不相等就让dest++,然后把src位置的值赋值到dest位置上,然后再让src++,听着可能有点懵,我们来画个图理解一下,就知道这个思路了
   具体的例子我们就参考题目给出的第一个示例,如下:
在这里插入图片描述
在这里插入图片描述
   有了上图的解析,我们现在就可以直接来写代码了,首先创建一个while循环,条件就是src<numsSize,因为src是数组的下标,不能越界
   然后如果src指向的元素等于dest指向的元素,就让src++,其它什么都不做,如果不相等,就让dest先++,再把src位置的元素赋值给dest位置的元素,最后让src++,如下:

while (src < numsSize)
{
    if (nums[src] == nums[dest])
    {
        src++;
    }
    else
    {
        dest++;
        nums[dest] = nums[src];
        src++;
    }
}

   写出来之后我们可以对它进行一下优化,让代码不那么臃肿,如下:

while (src < numsSize)
{
    if (nums[src] == nums[dest])
        src++;
    else
        nums[++dest] = nums[src++];
}

   最后循环结束后我们再返回dest+1即可,完整代码如下:

int removeDuplicates(int* nums, int numsSize) 
{
    int src = 0, dest = 0;
    while(src < numsSize)
    {
       if(nums[src] == nums[dest])
          src++;
       else
          nums[++dest] = nums[src++];
    }
    return dest+1;    
}

   最后就可以成功提交代码了,我们再来分析一下双指针法的时间复杂度和空间复杂度,我们只使用了一个循环,时间复杂度为O(N),只申请了有限个大小的空间,所以空间复杂度为O(1),相较于上一个方法优化了许多

3.双指针练习之合并两个有序数组

题目链接:https://leetcode.cn/problems/merge-sorted-array/description/

方法1(直接排序)

   虽然这道题我们是用来练习双指针的,但是我们还是有必要知道一下这道题的其它解决办法,并且这个解决方法还不难,所以放在这里简单说一下
   我们先来看看题目描述:
在这里插入图片描述
   题目第一个示例:
在这里插入图片描述
   题目给出的函数原型:
在这里插入图片描述
   题目的大致含义就是,给了我们两个数组,其中第一个数组nums1的大小是两个数组有效元素个数的和,因为我们后面要把nums2数组中的元素放到nums1中去,所以要保证nums1数组的大小足够
   首先题目还是告诉我们这两个数组是非递减的数组,也就是递增的数组,只是有可能有重复的数据,现在就要求我们将这两个有序的数组合并,并且保持合并后还是有序的
   第一个方法很简单,不是保持合并后还是有序吗,直接把nums2数组的数据先插入num1数组,然后对整个nums1数组进行排序,排序我们可以选择qsort函数,没有学过qsort函数的友友可以参考文章:【C语言】手把手带你拿捏指针(4)(含qsort函数详解)
   也可以选择我们之前学过的冒泡排序,但是其实冒泡排序的效率是比较低的,后面我们会把所有常见的排序算法都讲一下,比如快排,堆排等等,qsort函数的底层就是使用的快排实现
   代码的实现过程就不再多讲了,思路很简单,这里我们直接给出完整代码:

#include <stdlib.h>

int int_cmp(const void* e1, const void* e2)
{
    return *(int*)e1 - *(int*)e2;
}

void merge(int* nums1, int nums1Size, int m, int* nums2, int nums2Size, int n) 
{ 
   for(int i = 0; i<n; i++)
   { 
      nums1[i+m] = nums2[i]; 
   }  
   qsort(nums1, m+n, sizeof(int), int_cmp);
}

   可以看到代码的逻辑是很简单的,并且效率是很快的,因为qsort底层使用的是快排,时间复杂度仅仅为O(N * logN),空间复杂度也是O(1),那么还有没有更快的方法呢?当然有,就是我们马上介绍的双指针法

方法2(双指针)

   其实我们今天练习的三道题其实都很类似,所以都可以使用双指针来做,只是在这道题中我们有两个数组需要合并,我们还是可以试着用之前的思路来思考一下这道题,只是之前是一个数组,只需要一个src,这道题我们可以定义两个指针src1和src2
   之前的两个题思路就是,如果碰到相等的元素或者题目给出的元素,就把它跳过,使用后面的元素将它覆盖,而这道题我们该怎样做呢?
   首先就是第一个思路,我们定义src1指向nums1数组的第一个元素,src2指向nums2数组的第二个元素,然后由于要把最后的结果保存到nums1中,所以dest就指向nums1中的第一个元素
   随后我们比较src1指向的元素和src2指向的元素哪个小,哪个小就把它放到dest的位置上,然后让dest++,然后src1++或者src2++,最后循环这个步骤
   但是我们最后发现这个思路有点问题,问题出在nums1数组中,因为如果我们直接把数据放在dest,也就是从nums1数组的开头开始存放数据,会导致原本的nums1数组的数据被覆盖,我们举个例子,如图:
在这里插入图片描述
   此时我们就发现问题了,nums1中的数据会被覆盖,所以第一种思路并不可行,那么怎么避免数据被覆盖呢?这个时候我们就可以从nums1数组的最后面开始操作数据,也就是让我们的dest默认指向nums1数组的最后一个位置
   因为我们要保证nums1最后排序成相对递增,最后一个位置就要放最大的值,怎么办呢?我们可以让src1和src2分别指向nums1和nums2数组中有效元素的最后一个元素,然后它们两个指向的元素谁大就让它放入dest的位置
   然后让dest- -,以及src1- -或者src2- -,就这样一直从后往前找大放入dest位置,循环条件就是要让src1和src2都要大于等于0,因为它们是数组的下标,不能越界,最后就可以使得数组是相对递增的,这就是我们的第二个思路,接下来我们就用第一个示例来画个图理解一下:
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
   可以看到我们这里将两个数组合并到了nums1中,让数组nums1有序了,但是其实有一个问题,如果我们最后时src2先越界,那么说明nums2数组中的数据已经全部放入nums1了,循环结束了,剩下的nums1的数据也已经保持了有序,所以src2首先越界代码没有问题
   但是有可能下一次src1首先越界,说明nums1中原本的有效的元素已经放在nums1数组后面了,循环结束了,但是nums2数组还没有放完呀,这个时候就会出错,所以我们还需要在这个循环结束后用一个新的循环判断一下
   如果src2还大于等于0,说明nums2数组中的内容还没有全部移动到nums1中,此时我们只需要循环地让数组nums2中的元素移动到nums1的dest位置,接下来我们的代码才能完全没问题,如下:

void merge(int* nums1, int nums1Size, int m, int* nums2, int nums2Size, int n) 
{
    int src1 = m-1;
    int src2 = n-1;
    int dest = m+n-1;
    while(src1>=0 && src2>=0)
    {
        if(nums1[src1] > nums2[src2])
        {
            nums1[dest--] = nums1[src1--];
        }
        else
        {
            nums1[dest--] = nums2[src2--];
        }
    }
     while(src2 >=0)
    {
        nums1[dest--] = nums2[src2--];
    }
}

   接着我们提交一下:
在这里插入图片描述
   可以看到代码成功通过了,我们再来分析一下这个代码的时间复杂度和空间复杂度,可以发现我们虽然有两个循环,但是实际上深入计算会发现两个循环的次数加起来为O(N),所以时间复杂度是标准的O(N)
   并且由于申请的是有限个空间,所以空间复杂度是O(1),我们就可以看出来了,虽然我们的快排很快,时间复杂度仅为O(N * logN),但是我们的双指针更快,只有O(N)

   那么今天的分享就到这里结束啦,我们今天使用了顺序表来做了两道题,用一个题来专门学习双指针算法,但是这三道题都使用了我们的双指针算法来解决,以后类似的题就可以使用双指针,效率是很高的
   不知道友友们有没有收获什么新知识呢,欢迎在评论区留言,有问题欢迎直接私信我
   那么今天就撤啦,bye~

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

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

相关文章

机器学习—矩阵乘法

矩阵只是一个或两个数组。 如何在向量之间取点积&#xff1f; 让我们用列向量[1,2]*[[3,4]&#xff0c;如果z是这两个向量之间的点积&#xff0c;然后通过乘以第一个元素来计算z&#xff0c;通过这里的第一个元素&#xff0c;所以是1*3加第二个元素乘以第二个元素即2*4&#…

使用 ADB 在某个特定时间点点击 Android 设备上的某个按钮

前提条件 安装 ADB&#xff1a;确保你已经在计算机上安装了 Android SDK&#xff08;或单独的 ADB&#xff09;。并将其添加到系统环境变量中&#xff0c;以便你可以在命令行中运行 adb。 USB调试&#xff1a;确保 Android 设备已启用 USB 调试模式。这可以在设备的“设置” -…

数据结构之二叉树前序,中序,后序习题分析(递归图)

1.比较相同的树 二叉树不能轻易用断言&#xff0c;因为树一定有空 2.找结点值 3.单值二叉树 4.对称二叉树 5.前序遍历

[CUDA] 将已有的地址空间设置为pinned memory

文章目录 1. cudaHostRegitster的使用构建pinned memory1.1 基本使用1.2 cudaHostRegister 需要设置cudaSetDevice? Reference 1. cudaHostRegitster的使用构建pinned memory 注意使用C申请的内存空间&#xff0c;在进行copy是无法实现流的最大异步性&#xff1b;因此使用cud…

各种数据库介绍

1. 关系型数据库&#xff08;RDBMS&#xff09; MySQL • 特点&#xff1a;开源、免费&#xff0c;社区版功能强大且稳定。支持大量的并发连接&#xff0c;常用于Web应用。 • 适用场景&#xff1a;中小型网站、博客、电商等。 PostgreSQL • 特点&#xff1a;功能丰富&#xf…

ONLYOFFICE 8.2版本评测:超好用办公工具

前言 在技术的快速发展和工作方式的持续演进下&#xff0c;现代办公软件正变得越来越强大和多样化。ONLYOFFICE&#xff0c;作为市场上备受瞩目的一体化办公解决方案&#xff0c;以其全面的文档编辑、表格处理和演示制作功能&#xff0c;满足了用户在不同办公场景下的需求。最…

Python基础学习_01

目录 1、注释 2、数字和数学计算 3、变量 4、字符串 5、打印 6、本节总结 1、注释 • 什么是注释&#xff1f; 1&#xff09;注释就是用自然语言向代码阅读者说明代码的功能和意义 • 注释 1&#xff09;单行注释使用 # 为开头&#xff1b;并且不能换行…

不容错过的电脑监控软件TOP10|电脑屏幕监控软件推荐(收藏)

随着企业对员工管理和数据安全的要求日益提高&#xff0c;电脑监控软件已经成为许多公司确保工作效率、信息保密以及员工行为合规性的重要工具。无论是需要跟踪员工的工作进度&#xff0c;还是防止数据泄露和滥用&#xff0c;选择合适的监控软件至关重要。今天我们为你整理了十…

Python练习10

Python日常练习 题目&#xff1a; 编写程序&#xff0c;输出如下所示图案。 * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * 要求&#xff1a; 使用for循环的方式完成 --------------------------------------------------------- 注意&#xff1a; …

【DM系列】DM 集成 JDBC 开发指南

前言 数据库访问是数据库应用系统中非常重要的组成部分&#xff0c;DM 作为一个通用数据库管理系统&#xff0c;提供了多种数据库访问接口&#xff0c;包括 ODBC、JDBC、DPI 等方式。本开发指南详细介绍了 DM 的各种访问接口、相应开发环境的配置、以及一些开发用例。本指南的主…

长亭那个检测能力超强的 WAF,出免费版啦

告诉你们一个震撼人心的消息&#xff0c;那个检测能力超强的 WAF——长亭雷池&#xff0c;他推出免费社区版啦&#xff0c;体验地址见文末。 八年前我刚从学校毕业&#xff0c;在腾讯做安全研究&#xff0c;看到宇森在 BlackHat 上演讲的议题 《永别了&#xff0c;SQL 注入》 …

Excel 无法打开文件

Excel 无法打开文件 ‘新建 Microsoft Excel 工作表.xlsx",因为 文件格式或文件扩展名无效。请确定文件未损坏&#xff0c;并且文件扩展名与文件的格式匹配。

软件测试学习笔记丨SeleniumPO模式

本文转自测试人社区&#xff0c;原文链接&#xff1a;https://ceshiren.com/t/topic/22525 本文为霍格沃兹测试开发学社的学习经历分享&#xff0c;写出来分享给大家&#xff0c;希望有志同道合的小伙伴可以一起交流技术&#xff0c;一起进步~ 说明&#xff1a;本篇博客基于sel…

Nginx配置SSL证书(自签名证书)

1 生成自签名证书(生成证书方式一) # 生成私钥:server.key [rootlocalhost ~]# openssl genrsa -out server.key 2048# 生成证书请求文件:server.csr [rootlocalhost cert]# openssl req -new -key server.key -out server.csr Country Name (2 letter code) [XX]:cn 《这里…

汽车固态电池深度报告

固态电池符合未来大容量二次电池发展方向&#xff0c;半固态电池已装车&#xff0c;高端长续航车型、e-VTOL 等方向对固态电池需求明确。固态电池理论上具备更高的能量密度、更好的热稳定性、更长的循环寿命等优点&#xff0c;是未来大容量二次电池发展方向。根据中国汽车动力…

Linux网络命令:用于查看和修改路由表的重要工具ip route 详解

目录 一、概述 二、用法 1、基本语法 2、参数说明 3、常用选项 4、获取帮助 三、基本用法示例 1、 查看路由表 2、 添加路由 3、 删除路由 4、 修改路由 5、 添加默认路由 6、 删除默认路由 四、路由表管理 1、查看所有路由表 2、指定路由表 五、其他选项 1、…

02- 模块化编程-007 Ltc1684( ADC16-Bit)采样显示

1、Ltc1684芯片介绍 该芯片是一款高精度的16位模数转换器(ADC)&#xff0c;适合于高精度仪器的开发&#xff0c;它能提供精准的模拟信号到数字信号的转换。 特性 采用 MSOP 封装的 16 位、250ksps ADC 单 5V 电源 低电源电流&#xff1a;850μA (典型值) 自动停机功能可把电源…

Chrome与火狐哪个浏览器的移动版本更流畅

在当今的数字化时代&#xff0c;移动设备已经成为我们生活中不可或缺的一部分。而浏览器作为我们访问互联网的重要工具&#xff0c;其性能和用户体验直接影响到我们的使用感受。本文将对比Chrome和火狐&#xff08;Firefox&#xff09;两款主流浏览器的移动版本&#xff0c;探讨…

人工智能学习--归一化(Normalization)

概念 归一化是数据预处理中将不同量纲的特征数据缩放至同一尺度的过程&#xff0c;使特征值落在同一范围&#xff08;如[0, 1]或[-1, 1]&#xff09;。归一化有助于消除量纲影响&#xff0c;提升算法的收敛速度和模型稳定性&#xff0c;尤其在梯度下降和距离计算等算法中尤为重…

xrc的比赛

先看考试题&#xff0c;附加题最后再写 T1 首先看到是求逆序对为奇数的子串&#xff0c;发现只需要贪心 贪心发现求长度为2的逆序对最优&#xff0c;所以时间复杂度为 O ( n ) O(n) O(n)的贪心就能过了 #include<bits/stdc.h> using namespace std; int read() {int x…