当前位置: 首页 > news >正文

small用于不连续数组_左神直通BAT算法之找出B中不属于A的数

找出B中不属于A的数

找出数组B中不属于A的数,数组A有序而数组B无序。假设数组A有n个数,数组B有m个数,写出算法并分析时间复杂度。

方法一:遍历

首先遍历B,将B中的每个数拿到到A中找,若找到则打印。对应算法如下:

int A[] = {1, 2, 3, 4, 5};

int B[] = {1, 4, 2, 6, 5, 7};

for (int i = 0; i < 6; ++i) {

 int temp = B[i];

 bool flag = false;

 for (int j = 0; j < 5; ++j) {

   if (A[j] == temp) {

     flag = true;    //找到了

     break;

   }

 }

 if (!flag) {    //没找到

   printf("%d", temp);

 }

}

不难看出上述算法的时间复杂度为 O(m*n),因为将两个数组都遍历了一遍

方法二:二分查找

由于数组A是有序的,在一个有序序列中查找一个元素可以使用二分法(也称折半法)。原理就是将查找的元素与序列的中位数进行比较,如果小于则去掉中位数及其之后的序列,如果大于则去掉中位数及其之前的序列,如果等于则找到了。如果不等于那么再将其与剩下的序列继续比较直到找到或剩下的序列为空为止。

5ca47e48b3e9f393b4507c96d0162a5e.png

利用二分法对应题解的代码如下:

for (int i = 0; i < 6; ++i) {        //B的长度为6

 int temp = B[i];

 //二分法查找

 int left = 0,right = 5-1;            //A的长度为5

 int mid = (left + right) / 2;

 while (left < right && A[mid] != temp) {

   if (A[mid] > temp) {

     right = mid - 1;

   } else {

     left = mid + 1;

   }

   mid = (left + right) / 2;

 }

 if (A[mid] != temp) {

   printf("%d", temp);

 }

}

for循环 m次, while循环 logn次(如果没有特别说明,log均以2为底),此算法的时间复杂度为 O(mlogn)

方法三:排序+外排

第三种方法就是将数组B也排序,然后使用逐次比对的方式来查找A数组中是否含有B数组中的某元素。引入a、b两个指针分别指向数组A、B的首元素,比较指针指向的元素值,当 a<b时,向后移动a指针查找该元素;当 a=b时,说明A中存在该元素,跳过该元素查找,向后移动b;当 a>b时说明A中不存在该元素,打印该元素并跳过该元素的查找,向后移动b。直到a或b有一个到达数组末尾为止(若a先到达末尾,那么b和b之后的数都不属于A)

80b8bbaa05f5a846b9edc58f7380d8e7.png

对应题解的代码如下:

void fun3(int A[],int a_length,int B[],int b_length){

   quickSort(B, 0, b_length - 1);    //使用快速排序法对数组B排序->O(mlogm)

   int* a = A,*b=B;

   while (a <= A + a_length - 1 || b <= B + b_length - 1) {

       if (*a == *b) {

           b++;

           continue;

       }

       if (*a > *b) {

           printf("%d", *b);

           b++;

       } else {

           a++;

       }

   }

   if (a == A + a_length) {    //a先到头

       while (b < B + b_length) {

           printf("%d", *b);

           b++;

       }

   }

}

快速排序的代码如下:

#include

#include

//交换两个int变量的值

void swap(int &a, int &b){

   int temp = a;

   a = b;

   b = temp;

}

//产生一个low~high之间的随机数

int randomInRange(int low, int high){

   srand((int) time(0));

   return (rand() % (high - low))+low;

}

//快速排序的核心算法,随机选择一个数,将比该数小的移至数组左边,比该数大的移至

//数组右边,最后返回该数的下标(移动完之后该数的下标可能与移动之前不一样)

int partition(int arr[],int start,int end){

   if (arr == NULL || start < 0 || end <= 0 || start > end) {

       return -1;

   }

   int index = randomInRange(start, end);//随机选择一个数

   swap(arr[index], arr[end]);//将该数暂时放至末尾

   int small = start - 1;

   //遍历前n-1个数与该数比较并以该数为界限将前n-1个数

   //分为两组,small指向小于该数的那一组的最后一个元素

   for (index = start; index < end; index++) {

       if (arr[index] < arr[end]) {

           small++;

           if (small != index) {

               swap(arr[small], arr[index]);

           }

       }

   }

   //最后将该数放至数值较小的那一个组的中间

   ++small;

   swap(arr[small], arr[end]);

   return small;

}

void quickSort(int arr[],int start,int end) {

   if (start == end) {

       return;

   }

   int index = partition(arr, start, end);

   if (index > start) {

       quickSort(arr,start, index - 1);

   }

   if (index < end) {

       quickSort(arr, index + 1, end);

   }

}

此种方法的时间复杂度为: O(mlogm)(先对B排序)+ O(m+n)(最坏的情况是指针a和b都到头)。

三种方法的比较

  1. O(m*n)

  2. O(mlogn)(以2为底)

  3. O(mlogm)+O(m+n)(以2为底)

易知算法2比1更优,因为增长率 logn<n。而2和3的比较取决于样本量m和n之间的差距,若 m>>n那么2更优,不难理解:数组B元素较多,那么对B的排序肯定要花费较长时间,而这一步并不是题解所必需的,不如采用二分法;相反地,若 m<<n,那么3更优。

出自:http://www.zhenganwen.top

已获授权

作者是前腾讯员工/现创业公司员工,致力于分享leetcode/剑指offer/算法题解/互联网时事/编程资源,觉得不错关注转发一下。

2dd70e0955b65c9e40f271a9bf5e9b47.png

相关文章:

  • python接口自动化测试报告_python接口自动化(二十八)--html测试 报告——下(详解)...
  • python对键和值有没有类型限制_python基础之-数据类型
  • python编程小白变大神_零基础Python,从小白到大神的方法全在这了!
  • 如果表不存在则创建_当创建一个文件的时候,操作系统发生了什么
  • 胖终端和瘦终端的区别_企业级无线覆盖与家庭级无线覆盖的区别与发展趋势
  • pythonnode js结合_Node js 和 python 混合编程之JSON入参的区别 如何转换js对象使其能在python脚本中作为python 字典直接使用...
  • sql 统计每月入职离职人数_说离职就离职,他们就不害怕失业吗,为什么90后的离职率那么高...
  • redis 端口_基础架构之Redis
  • python check module_Python 的 module 机制(重要)
  • springboot技术架构图_阿里技术专家告诉你:如何画出优秀的架构图
  • python嗅探m3u8_python通过m3u8下载视频
  • 安装python3.6.1的步骤_在Linux上安装Python3.6.1
  • python单词按字典序输出_python – 我可以通过匹配键作为前缀在字典中保留新单词...
  • 后台页面需要设置登录过期时间吗_电商后台优惠券设计
  • 机械制图符号_机械图纸感觉每一个都很复杂,这12个机械制图的简化画法,你会吗...
  • angular组件开发
  • Codepen 每日精选(2018-3-25)
  • ECMAScript 6 学习之路 ( 四 ) String 字符串扩展
  • extract-text-webpack-plugin用法
  • Fundebug计费标准解释:事件数是如何定义的?
  • JavaScript函数式编程(一)
  • JavaScript异步流程控制的前世今生
  • Java面向对象及其三大特征
  • Java小白进阶笔记(3)-初级面向对象
  • Js基础——数据类型之Null和Undefined
  • Vue 重置组件到初始状态
  • Vue实战(四)登录/注册页的实现
  • Webpack4 学习笔记 - 01:webpack的安装和简单配置
  • 从0实现一个tiny react(三)生命周期
  • 从零搭建Koa2 Server
  • 第13期 DApp 榜单 :来,吃我这波安利
  • 多线程 start 和 run 方法到底有什么区别?
  • 规范化安全开发 KOA 手脚架
  • 互联网大裁员:Java程序员失工作,焉知不能进ali?
  • 让你的分享飞起来——极光推出社会化分享组件
  • 三栏布局总结
  • 删除表内多余的重复数据
  • 使用 Docker 部署 Spring Boot项目
  • 吴恩达Deep Learning课程练习题参考答案——R语言版
  • 一个6年java程序员的工作感悟,写给还在迷茫的你
  • #设计模式#4.6 Flyweight(享元) 对象结构型模式
  • (10)工业界推荐系统-小红书推荐场景及内部实践【排序模型的特征】
  • (C)一些题4
  • (Java岗)秋招打卡!一本学历拿下美团、阿里、快手、米哈游offer
  • (solr系列:一)使用tomcat部署solr服务
  • (四)汇编语言——简单程序
  • (原創) 是否该学PetShop将Model和BLL分开? (.NET) (N-Tier) (PetShop) (OO)
  • (转)3D模板阴影原理
  • (转)Google的Objective-C编码规范
  • (转)iOS字体
  • (转)视频码率,帧率和分辨率的联系与区别
  • .NET Framework 4.6.2改进了WPF和安全性
  • /dev下添加设备节点的方法步骤(通过device_create)
  • @column注解_MyBatis注解开发 -MyBatis(15)
  • @软考考生,这份软考高分攻略你须知道