左神算法与数据结构——基础提升大数据

这篇博客探讨了大数据处理的高效算法,包括位图法找缺失数、有限空间内的计数优化、利用堆排序求Top100、整数翻转与符号判断、2的幂与4的幂判断,以及加减乘除的位运算实现。内容涵盖了数据结构、算法优化和位操作技巧。
摘要由CSDN通过智能技术生成

大数据

题目一

在这里插入图片描述

普通解法:利用位图,将32位的整数分别对应到个数为2^32次位图数组中,其大小为500M,则可以找到40亿个中不存在的数。

在这里插入图片描述

进阶解法:例如只给3KB,则找到512为离3000/4最近的2的幂指数,将32位数均匀分成512份,每份有836088个数,再将40亿个数每个/836088,发现哪份少了就利用3KB空间对该份进行细分,直至分出每份为1的份数。

进阶解法2:只能申请有限个变量。二分,统计词频,找到不满的继续分。

题目二

在这里插入图片描述

经典方法:可以利用哈希函数或者布隆过滤器。

补充问题:利用二维堆来解决

  • 将海量词汇利用哈希函数进行离散化分类,再根据要求取模,分层k堆,每个堆为大根堆进行排序。
  • 设置一个总堆为大根堆。首先将每个堆的第一个元素放入总堆中,弹出一个最大的,再将这个最大的所在堆中第二大的放入,再进行弹出操作。直至找到top100。

在这里插入图片描述

题目三

在这里插入图片描述

  • 常规解法:可以利用两个bit来表示该数出现过的次数,其中10代表出现过两次。预计使用小于1G的空间。

在这里插入图片描述

  • 补充解法:例如用10KB空间,其最多可以放2048个无符号整型数组数据,将2^32个数字范围分成2048份,再对40亿个数进行计数,若全部计数完毕后第k个区间包含了第20亿个数,则再在该区间进行细分。

在这里插入图片描述

腾讯题

在这里插入图片描述

10G文件存放无序整型数据,如何利用6G内存,将其变为有序文件。

  • 例如分成25个小根堆,每个小根堆含有227个数,按照其分类

在这里插入图片描述

  • 优化方案:例如有10条数据,有容量为3的大跟堆。遍历所有数据,若大根堆中数据个数小于3则放入,若小于大根堆顶端数据,则放入,否则忽略。一遍遍历完后,将最小的3个数输出,接着重新遍历,但不放进已经放入过的数据。

在这里插入图片描述

题目四

在这里插入图片描述

public static int flip(int n) {
		return n ^ 1; // 进行翻转
	}

	public static int sign(int n) {
		return flip((n >> 31) & 1); // 找到符号位
	}

	public static int getMax1(int a, int b) {
		int c = a - b; // 比较a和b
		int scA = sign(c); //a和b之差的正负 
		int scB = flip(scA); //a和b之差的正负 的相反数
		return a * scA + b * scB;
	}

	public static int getMax2(int a, int b) {
		int c = a - b;// 比较a和b
		int sa = sign(a); // a的正负
		int sb = sign(b); // b的正负
		int sc = sign(c); // a-b的正负
		int difSab = sa ^ sb; // a和b符号不一样为1;一样为0
		int sameSab = flip(difSab); // a和b符号不一样为0;一样为1
		int returnA = difSab * sa + sameSab * sc; // a和b符号不一样为1且a>0,a和b符号一样且a>b
		int returnB = flip(returnA);
		return a * returnA + b * returnB;
	}

题目五

在这里插入图片描述

  1. 判断2的幂
  • 在二进制下只有一位是1
  • 法1:拿到这个数最右侧的1: x & (~ x + 1),看与该数是否相等,相等则符合。
  • 法2:x & (x - 1) == 0 则只有一位1
  1. 判断4的幂
  • 在二进制上只有一个1,且1必须在0、2、4、6、8···位上
  • 首先去验证是2的幂
  • 接着验证x & 010101010101 != 0则为4的幂

题目六

在这里插入图片描述

加法:

  • 异或运算相当于无进位相加
  • 进位信息可以由两数与运算并左移得到
  • 再将其不断进行以上操作,直至进位信息为0,则答案为异或运算结果

在这里插入图片描述

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为a加上b的相反数,b的相反数为b取反再加1

乘法:

`int multi(int a, int b) {
  	int res = 0;
  	while (b != 0) {
  		if ((b & 1) != 0) {// b的最后一位不为0
  			res = add(res, a);
  		}
  		a = (a << 1);
  		b = ((unsigned)b >> 1);//无符号右移
  	}
  	return res;
  }`

在这里插入图片描述

除法:

  • 让除数分别左移31…0位,让被除数尝试去减,假设左移3位可以减,则商的结果中第4位一定是1,然后将被除数减后的结果当作新的被除数,重复上述操作
int myDiv(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 >= 0; i--) {
  		if ((x >> i) >= y) {
  			res = (res | (1 << i));
  			x = minuss(x, (y << i));
  		}
  	}
  	return isNeg(a) ^ isNeg(b) ? negNum(res) : res;
  }

在这里插入图片描述

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值