剑指offer 面试题3:数组中重复的数字

本文探讨了在长度为n的数组中查找重复数字的三种高效算法:排序法、哈希法和交换法,详细解释了每种方法的实现原理及时间、空间复杂度。

题目描述:找出数组中重复的数字

    在一个长度为n的数组中,所有数字都在0~n-1的范围内。数组中某些数字是重复的,但是不知道几个数字重复了,也不知道数字重复了几次。请找出数组中所有的重复的数字。例如:一个长度为7的数组{2,3,1,0,2,5,3},数组中重复的数字是2和3。


解法一:排序法。把数组中的数字进行排序,在排序后的数组中扫描。在众多排序算法中,选择快速排序可以比简单选择排序和冒泡排序的时间复杂度低,而且编码也比较简单。采用这种方法的时间复杂度为:O(nlog(n))。

示例代码:

#include <iostream>

using namespace std;

void quicksort(int *a,int left,int right)
{
     int i = left, j=right, t;
     if (left > right)
     {
        return;
     }
     int tmp = a[left];
     while(i != j) 
     {
         while (a[j] >= tmp && j > i)
         {
               j--;
         }
         if(j > i)
         {
              a[i] = a[j];//a[i]已经赋值给tmp,a[j]赋值给a[i]之后 ,a[j]留出空位 
         }
         
         while(a[i] <= tmp && i < j) 
         {
               i++;
         }
         if(i < j)
         {
              a[j] = a[i];//此时a[i] 空出来了 
         }
     }
     a[i] = tmp;
     quicksort(a,left,i-1);
     quicksort(a,j+1,right);
}

int main()
{
    int a[] = {2,3,1,0,2,2,2,5,3};
    quicksort(a,0,8);
    for(int i = 0;i < 9; i++)
    {
            printf("%d ",a[i]);
    }
    printf("\n");
    int flag = 0;
    for(int i = 1;i < 9; i++)
    {
            if(a[i] == a[i+1])
            {
                    flag = 1;
            }
            else if(flag == 1)
            {
                 printf("%d ",a[i]);
                 flag = 0;
            }
    }
    printf("\n");
    getchar();
    return 0;
}

解法二:哈希法。扫描数组中的每个元素,同时把每个元素作为键,元素在数组中出现的次数作为值存储在哈希表中,经过一轮扫描之后,在哈希表中记录了数组中每个元素出现的次数。然后遍历哈希表,即可找出数组中重复的元素。采用这种方法的时间复杂度为O(n),空间复杂度为O(n)。因此,可以认为解法二提高时间复杂度是以牺牲了空间为代价的。

示例代码:

#include <iostream>
#include <map>

using namespace std;

int main()
{
    int a[] = {2,3,1,0,2,5,3};
    map<int,int> my_map;
    for(int i = 0;i < 7; i++)
    {
            if(my_map.find(a[i]) == my_map.end())
            {
                 my_map[a[i]] = 1;
            }
            else 
            {
                 my_map[a[i]]++;
            }
    }
    
    for(map<int,int>::iterator iter = my_map.begin();iter != my_map.end();iter++)
    {
        if(iter->second > 1)
        {
            printf("%d ",iter->first);
        }
    }
    printf("\n");
    getchar();
    return 0;
}

解法三:交换法。题中给出的是一个长度为n的数组,数组的下标是0~n-1,数组中的数字也是0~n-1。因此,当数组中不存在重复数字且排序之后,数字i将出现在下标为i的位置。由于数组中存在重复数字,因此,按照上面的思路,存在有的位置没有数字,有的位置要存放多个相同的数字。

    根据这种思路,我们可以采用交换法解决这个问题。扫描数组,每扫描一个数字,就比较当前数字是否与其下标相等,若相等,继续向后扫描;若不相等,比较以该数字为下标的元素是否与该元素相等,若相等,说明该元素是一个重复元素,向后扫描,否则,交换该元素和数组中以该元素为下标的元素。

示例代码:

#include <iostream>

using namespace std;

int main()
{
    int a[] = {2,3,1,0,2,5,3,2,3};
    int t;
    for(int i=0;i<9;) 
    {
       if(a[i] != i)     
       {
            if(a[a[i]] == a[i]) 
            {
                printf("%d ",a[i]);
                i++;
            } 
            else
            {
                t = a[i];
                a[i] = a[a[i]];
                a[a[i]] = t;
            } 
       }
       else
       {
       		i++;
	   }
    }
    return 0; 
}

有新想法或者问题欢迎留言。

内容概要:本文详细介绍了一种基于Simulink的表贴式永磁同步电机(SPMSM)有限控制集模型预测电流控制(FCS-MPCC)仿真系统。通过构建PMSM学模型、坐标变换、MPC控制器、SVPWM调制等模块,实现了对电机定子电流的高精度跟踪控制,具备快速动态响应和低稳态误差的特点。文中提供了完整的仿真建模步骤、关键参设置、核心MATLAB函代码及仿真结果分析,涵盖转速、电流、转矩和三相电流波形,验证了MPC控制策略在动态性能、稳态精度和抗负载扰动方面的优越性,并提出了参自整定、加权代价函、模型预测转矩控制和弱磁扩速等优化方向。; 适合人群:自动化、电气工程及其相关专业本科生、研究生,以及从事电机控制算法研究与仿真的工程技术人员;具备一定的电机原理、自动控制理论和Simulink仿真基础者更佳; 使用场景及目标:①用于永磁同步电机模型预测控制的教学演示、课程设计或毕业设计项目;②作为电机先进控制算法(如MPC、MPTC)的仿真验证平台;③支撑科研中对控制性能优化(如动态响应、抗干扰能力)的研究需求; 阅读建议:建议读者结合Simulink环境动手搭建模型,深入理解各模块间的信号流向与控制逻辑,重点掌握预测模型构建、代价函设计与开关状态选择机制,并可通过修改电机参或控制策略进行拓展实验,以增强实践与创新能力。
根据原作 https://pan.quark.cn/s/23d6270309e5 的源码改编 湖北省黄石市2021年中考学试卷所包含的知识点广泛涉及了中学学的基础领域,涵盖了实、科学记法、分式方程、几何体的三视图、立体几何、概率统计以及代方程等多个方面。 接下来将对每道试题所关联的知识点进行深入剖析:1. 实与倒的定义:该题目旨在检验学生对倒概念的掌握程度,即一个a的倒表达为1/a,因此-7的倒可表示为-1/7。 2. 科学记法的运用:科学记法是一种表示极大或极小数字的方法,其形式为a×10^n,其中1≤|a|<10,n为整。 此题要求学生运用科学记法表示一个天文单位的距离,将1.4960亿千米转换为1.4960×10^8千米。 3. 分式方程的求解方法:考察学生解决包含分母的方程的能力,题目要求找出满足方程3/(2x-1)=1的x值,需通过消除分母的方式转化为整式方程进行解答。 4. 三视图的辨认:该题目测试学生对于几何体三视图(主视图、左视图、俯视图)的认识,需要识别出具有两个相同视图而另一个不同的几何体。 5. 立体几何与表面积的计算:题目要求学生计算由直角三角形旋转形成的圆锥的表面积,要求学生对圆锥的底面积和侧面积公式有所了解并加以运用。 6. 统计学的基础概念:题目涉及众、平均、极差和中位的定义,要求学生根据提供的据信息选择恰当的统计量。 7. 方程的整解求解:考察学生在实际问题中进行学建模的能力,通过建立方程来计算在特定条件下帐篷的搭建方案量。 8. 三角学的实际应用:题目通过在直角三角形中运用三角函来求解特定线段的长度。 利用正弦定理求解AD的长度是解答该问题的关键。 9. 几何变换的应用:题目要求学生运用三角板的旋转来求解特定点的...
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值