算法与数据结构——大数据题目(java)(b站左程云课程笔记总结)

本文探讨了大数据处理中的各种算法技巧,包括哈希函数、布隆过滤器、一致性哈希、并查集、位图和堆的使用。通过位图和布隆过滤器节省空间,解决集合查询和数据服务器负载问题。还介绍了如何利用位运算和堆解决计算问题,如找中位数和有序文件迁移。此外,文章讲解了加减乘除的位运算实现,以及判断数字特性,如2的幂和4的幂的方法。
摘要由CSDN通过智能技术生成

大数据题目解题技巧

资源限制类题目

  1. 哈希函数可以把数据按照种类均匀分流(比较万能)
  2. 布隆过滤器用于集合的建立与查询,可以节省大量空间
  3. 一致性哈希解决数据服务器的负载管理问题
  4. 利用并查集结构做岛问题的并行计算
  5. 位图解决某一范围上数字的出现情况,并可以节省大量空间
  6. 利用分段统计思想,并进一步节省大量空间
  7. 利用堆、外排序来做多个处理单元的结果合并

位图解决某一范围上数字的出现情况,并可以节省大量空间

image-20220625165333616

布隆过滤器中提过的位bit

位图:2^32/32等于128MB,即申请一个128MB的整型数组,就可以表示所有数字有没有出现过(0、1)

进阶问题:

先把全部内存拿去生成一个整型数组,假设现在给的内存是3kb,则此时能生成一个大小为3000/4的int数组,3000/4约等于700,向下取最接近的2的某次方,即512,题目范围是0-232-1,长度为512的int数组能表示512x32=16384个数是否出现过的信息,一共有232个数,除以16384等于262144,该数组可以区分16384的数信息

此时每进来一个数,就除以262144得到一个0-16384之间的数,数组中对应的索引上的数++,40亿个数全部统计完的时候,肯定有小于262144的数,就可以知道缺的数字来自哪个范围,然后就可以在该范围继续用16384去分(还是用40亿个数去检验),周而复始就能定位到没出现过的数字

题目二

image-20220702102629185

哈希:分到不同的机器或不同的时间分到同一台机器进行统计,同一种url会进一个文件,在每个文件(机器)中进行统计

布隆过滤器:每次添加之前进行查询操作,如果已经加入过(即重复),则将重复的url记录在文件中,有失误率

补充题:

二维堆

同样使用哈希分流将词汇分流到不同的小文件中,每个小文件中包含的是大根堆(词频),每个小文件的堆顶拿出来单独再组成一个大根堆(总堆),把总堆的堆顶弹出即词汇量排名第一的,然后找到该词汇对应的小文件,把小文件的堆顶弹出并把新的堆顶加入到总堆中,周而复始,直到弹出100个数,都是堆,时间复杂度都是O(logN),代价低

题目三

image-20220702104033405

可以使用万能的哈希来处理,取hash+取模的方式,同一个数会进入同一个文件,再用哈希表等方式统计即可

升级的位图

用两个位来表示一个数出现的状态

00表示出现0次

01表示出现1次

10表示出现2次

11表示出现了2次以上

40亿个数*2位即80亿位

80亿/8字节=10亿字节<1GB

2^32个数经过上述处理刚好是1GB的内存

补充题

分段思想,假设现在要求更加严格,是10KB,看10KB能申请一个多长的无符号整型数组,10KB/4B=2500,取小于等于的最大2的次方数2048,现在范围是0-232-1,所有数的范围可以被等分成2048份,232/2048=2097152,即0-2097151是第一个范围,40亿个数每进来一个就除以2097152看落在哪个范围,例如1/2097152=0,数组0索引上对应的数+1,统计词频,全部数字都统计完成之后,记录从arr[0]+arr[1]+arr[2]直到该数等于或大于20亿,就可以直到中位数再哪个范围,就可以知道在某一个长度为2097152的范围上有中位数,再将该范围的数等分成2048份,重复上述操作,最终就可以得到全局的中位数

补充题目:腾讯原题

给定一个10GB的文件,里面放着无序的int整型数,现在一定的内存(5GB、5KB…),要求将原先再文件中的数都放到另一个文件中并且保证有序

方法一

内存所使用的数据结构是小根堆,小根堆中存放的是数以及出现的次数,根据数值组织,每条数据八个字节,都是int类型,小根堆都还有其他存储空间的消耗,假设每条数据16字节,5GB的内存可以存放5GB/16≈228字节条数据(1GB=230字节),该文件中存放的数范围是-231~231-1,可以将该范围的数均分成232/228=24份,将文件中所有的数都除以24,只关注在第一个范围上的数(即-231~(-231+228-1)),不在该范围上的数忽略,重复的数在小根堆中是以value词频的形式出现,然后小根堆一个个往外弹出加入到新文件中,以小根堆中的数据的key作为数字,value作为次数,小根堆全部依次弹出后,再关注下一个范围上的数,依次进行24次,完成文件迁移以及结果有序

题目四

位运算

image-20220702113503512

//实现一个函数,n是非负数就返回1,n是负数就返回0,不使用比较的方式
public int sign(int n){
    return flip((n>>31)&1);//n右移31位就是符号位
}

//保证输入参数n不是1就是0 输入1的话输出0 输入0的话输出1
public int filp(int n){
    return n^1;
}


//此方法有问题,a-b可能会溢出
public int getMax1(int a,int b){
    int c=a-b;
    int scA=sign(c);//a-b为非负的话,scA为1  a-b为负数的话,scA为0
    int scB=flip(scA);//scA为0,scB就为1;scA为1,scB就为0
    return a*scA+b*scB;//返回较大的那个数  互斥条件相加替代了比较的过程
}

//a和b的符号相同的话就不会溢出,溢出的情况只会发生在a和b符号不同的情况
//返回a有两种情况,第一种:a和b相同且a-b>=0  第二种:a和b不相同且a>0
public int getMax2(int a,int b){
    int c=a-b;
    int sa=sign(a);
    int sb=sign(b);
    int sc=sign(c);
    int difSab=sa^sb;//a和b的符号不一样,就为1,a和b的符号一样就为0
    int sameSab=flip(difSab);//a和b的符号一样,就为1,a和b的符号不一样就为0
    int returnA=difSab*sa+sameSab*sc;//a的总状态
    int returnB=flip(returnA);//b的总状态与a的总状态互斥
    return a*returnA+b*returnB;
}

题目五

image-20220702171045069

2的幂二进制位上只有一个是1,其他都是0

方法一:得到这个数最右侧的1,判断这个数是不是与原来的数相等 A&(~A+1)

方法二:判断x&(x-1)是否等于0

public boolean is2Power1(int n){
    return (n&(~n+1))==n;
}

public boolean is2Power2(int n){
    return (n&(n-1))==0;
}

判断是否是4的幂,首先判断是否是2的幂

如果不是2的幂就也不是4的幂

如果是2的幂说明只有一个1

而4的幂的特征是那个1的位置在奇位数上

再和01010101…01这个数做&操作,结果等于0,则不是4的幂,不等于零则是4的幂

image-20220702172339196

public boolean is4Power(int n){
    return (n&(n-1))==0&&(n&0x55555555)!=0;//0x55555555就是01010101....01这个数
}

题目六

image-20220702173310982

加法

异或^:无进位相加

两个数相加=无进位相加+进位信息

进位信息=两数求与&再往左移动一位

再将异或结果和进位结果做相同操作直到进位结果为0,此时的异或结果就是答案

image-20220703103123652

public int add(int a,int b){
    int sum=a;
    while(b!=0){
        sum=a^b;
        b=(a&b)<<1;
        a=sum;
    }
    return sum;
}

减法

减法就是a+b的相反数

b的相反数就是取反+1

public int minus(int a,int b){
    return add(a,negNum(b));
}

public int negNum(int n){
    return add(~n,1);
}

乘法

小学乘法计算

image-20220703104131296

public int multi(int a,int b){
    int res=0;
    while(b!=0){
        if((b&1)!=0){//b的最后一位等于1才会进入
            res=add(res,a);
        }
        a<<=1;
        b>>>=1;
    }
    return res;
}

除法

a/b:b尽可能地向左移动,但不要超过a

乘法的逆向思维

比如b向右移动了三位,说明要得到的结果从右往左数第四位是1

然后将a与b右移三位的数做差

将做差的结果与b再做上述操作,看右移几位然后判断

最后有余数不管(计算机除法)

image-20220703111849414

public int div(int a,int b){
    int x=isNeg(a)?negNum(a):a;
    int y=isNeg(b)?negNum(b):b;
   	int res=0;
    for(int i=31;i>-1;i=minus(i,1)){
        if((x>>i)>=y){//这里使用x右移的方式更加安全
            res|=(1<<i);
            x=minus(x,y<<i);
        }
    }
    return isNeg(a)^isNeg(b)?negNum(res):res;
}

nt y=isNeg(b)?negNum(b):b;
int res=0;
for(int i=31;i>-1;i=minus(i,1)){
if((x>>i)>=y){//这里使用x右移的方式更加安全
res|=(1<<i);
x=minus(x,y<<i);
}
}
return isNeg(a)^isNeg(b)?negNum(res):res;
}


  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值