(12)杂

#include <iostream>
#include <string>


using namespace std;

void TestDataStructureBitMap();

/*
	给40亿个不重复的unsigned int的整数,没排过序的,然后再给一个数,
	如何快速判断这个数是否在那40亿个数当中
	1.位图算法
	2.Hash算法
	3.如何利用不用排序?

	不用一次把所有的都读入内存啊?
*/

/*
	LZW压缩算法:字串中的重复越多,压缩效果越好
*/
/*
	一个文件中含有n个元素,只能遍历一遍,要求等概率随机取出其中之一

*/

/*
	大数据处理
	1.位图
	2.Hash
	3.分割,分块处理
*/

/*
	海量日志数据,提取出某日访问百度次数最多的那个IP
	思路:将32位的IP地址,划分为32份。
	以最后5位为划分标准
*/

// 读取文件的IP地址内容:
// ip1:0xf0110504
// 以最后五位作为划分依据
//  以data1...data32
/*
	ip && 0x1f:得到最后五位。
	将(ip >> 5)存入文件
	将文件排序,扫描排好序的数据,并得到每个数据出现的次数。
	并记录每个文件中出现次数最多的ip,(ip << 5) | 0x...得到真实的ip地址
*/

const int FILE_NUM = 32;

// 只需要扫描一遍,保存32个文件句柄就可
// 不用排序,只需扫描一遍,并将次数保存即可
unsigned CalculateIP(const char *fileName);

// 将一个文件分成32个小文件
// i 表示最后5位的值
void DivideIPFile(const char *fileName, unsigned i);

// 对小文件进行内部排序,然后统计,并返回次数最多的,以及出现的次数
void SortCountIPFILE(const char *fileName, unsigned &ip, unsigned &count);

// 生成小文件的文件名:datai
void GetFileName(char *str, char unsigned i);

// 对二维数组进行扫描返回最大的
unsigned GetMostCommon(unsigned IPs[][32]);

/*	
	回文数:
	1.直接扫描判断
	2.递归判断
*/	
bool IsPalindrome(const char *str, int n);

// 返回字符串中最长的回文数的长度
unsigned LongestPalindromeOfString(const char *str, int n);


/*
	全排列:
		1.递归实现
		2.
*/
const int PERMUTATION_LEN = 128;
void Permutation(char *arr, unsigned n, unsigned first, char result[][PERMUTATION_LEN], unsigned &num, unsigned &len);

/*
	跳台阶:
		1.f(n) = f(n-1) + f(n-2)
	一个人上台阶可以一次上1个,2个,或者3个:
		f(n) = f(n-1)+f(n-2)+f(n-3)
		2.递推法
*/
// 递推法求:f(n) = f(n-1)+f(n-2)+f(n-3)
int DiTui(unsigned n);

int DiTui_2(unsigned n);
	

/*
	调整数组顺序使奇位于偶前面。 
	题目:输入一个整数组, 调整数中数字的顺序使得所有奇位于前半部分。要求时间复杂度为 O(n) 。
	1.头、尾设置两个指针,分别从前往后扫描
*/
void EvenBeforOdd(int *arr, unsigned n);

/*
	input:	1, 7, -5, 9, -12, 15
	output:	-5, -12, 1, 7, 9, 15
	O(N) O(1)
*/
/*
	在一个字符串中找到第只出现次的。
	abaccdeff:b
	1.hash[i] 扫描一遍记录字母出现的次数。再扫描一遍,找出出现一次的
	2.
*/

/*
	一致性哈希算法:
	1.传统Hash算法:增加或减少服务器时,需要重新计算

*/

/*
	题目:数组中有一个数字出现的次数超过了数组长度的一半,找出这个数字
	1.hash
	2.设置candidate
*/
/*	
	如果candidate与arr[i]相同,count++
	否则:count--
		如果count=0,则重置candidate为arr[i]
*/
int FindLongest(int *arr, unsigned n);

/*
	找出出现次数刚好是一半的数字
*/

/*
	给定一段产品的英文描述,包含M个英文字母,每个英文单词以空格分隔,无其他标点符号;
	再给定N个英文单词关键字,请说明思路并编程实现方法
	String extractSummary(String description,String[] key words)
	目标是找出此产品描述中包含N个关键字(每个关键词至少出现一次)的长度最短的子串,作为产品简介输出
	1.找子句
	2.子句中包含N个关键词,每个关键词至少出现一次
*/
/*
	1.以description中的每一个单词为起点,逐次找到包含N个关键词的子句(O(M^2))
	2.	a)先遍历description一遍,找出所有的关键词(O(M*log(N))),假设description中关键词为S个
		b)遍历关键词表(O(S^2))
	3.
*/

/*
	在一个二维数组中,每一行都按照从左到右递增的顺序排序,
	每一列都按照从上到下递增的顺序排序。
	请完成一个函数,输入这样的一个二维数组和一个整数,判断数组中是否含有该整数。
	1.分治法:
		
	2.从右上角开始。
		比数大:左
		比数小:下
*/
void FindMetrixNum(int **arr, int M, int N, int &x, int &y, int num);

// 分治法
void FindMetrixNum_2(int **arr, int M, int N, int &x, int &y, int num);

// 二分查找
int BinarySearch_2(int *arr, unsigned n, int num);

// 生成倒排索引

#include <fstream>
#include <assert.h>
#include <string>

#include "12_DataStructureBitMap.h"


void TestDataStructureBitMap()
{
	/*char str[7] = {0};
	GetFileName(str, 10);
	cout << str << endl;*/

	char str[] = "AB";
	char result[128][PERMUTATION_LEN];
	unsigned first = 0;
	unsigned num, len;
	Permutation(str, strlen(str), first, result, num, len);
}

unsigned CalculateIP(const char *fileName)
{	
	// IPs[0][i] = ip
	// IPs[1][i] = count
	unsigned IPs[2][32];

	// 1.将文件分成32个小文件
	for (unsigned i = 0; i < FILE_NUM; ++i)
	{
		DivideIPFile(fileName, i);
		char str[7];
		GetFileName(str, i);
		unsigned ip;
		unsigned count;
		// 2.将小文件进行内部排序
		SortCountIPFILE(str, ip, count);
		IPs[0][i] = (ip << 5) | i;
	}
	return GetMostCommon(IPs);

}

void DivideIPFile(const char *fileName, unsigned i)
{
}

void SortCountIPFILE(const char *fileName, unsigned &ip, unsigned &count)
{
	
}

void GetFileName(char *str, char unsigned i)
{	
	sprintf(str, "data%d", i);
}

unsigned GetMostCommon(unsigned IPs[][32])
{
	return 0;
}

bool IsPalindrome(const char *str, int n)
{
	assert(str);
	char *start = const_cast<char *>(str);
	char *end = const_cast<char *>(str + n - 1);
	while (start < end)
	{
		if (*start++ != *end--)
		{
			return false;
		}
	}
	return true;
}
/*
	回文数:
	1.单项链表:
		先定位到中间:用快慢指针,一个一次走一步,两一个一次走两步
	2.栈:
*/

unsigned LongestPalindromeOfString(const char *str, int n)
{
	assert(str);
	unsigned maxLen = 0;
	for (unsigned i = 0; i < n; ++i)
	{
		// 中间有一个字母的 str[i] 为中间数
		unsigned j = 0;
		for (; (i - j >= 0) && (i + j < n); ++j)
		{
			if (str[i - j] != str[i + j])
			{
				break;
			}
		}
		if ((i - j < 0) || (i + j >= n))
		{
			unsigned tmp = 2 * j + 1;
			if (tmp > maxLen)
			{
				maxLen = tmp;
			}
		}
		// 中间有两个字母的
		for (j = 0; (i - j >= 0) && (i + j + 1 < n); ++j)
		{
			if (str[i - j] != str[i + 1 + j])
			{
				break;
			}
		}
		if ((i - j < 0) || (i + j + 1 >= n))
		{
			unsigned tmp = 2 * j + 2;
			if (tmp > maxLen)
			{
				maxLen = tmp;
			}
		}
	}

	return maxLen;
}

void Permutation(char *arr, unsigned n, unsigned first, char result[][PERMUTATION_LEN], unsigned &num, unsigned &len)
{
	if (first + 1 == n)
	{
		result[0][0] = arr[first];
		result[0][1] = '\0';
		num = 1;
		len = 1;
		return;
	}
	for (unsigned i = first; i < n; ++i)
	{
		//int tmp = arr[i];
		swap<char>(arr[first], arr[i]);
		unsigned num1, len1;
		Permutation(arr, n, first + 1, result, num1, len1);
		for (unsigned j = 0; j < num1; ++j)
		{
			result[j][len1] = arr[first];
			result[j][len1 + 1] = '\0';
		}
		len = len1 + 1;
		num = num1 * 2;
		swap<char>(arr[i], arr[first]);
	}
}
int DiTui(unsigned n)
{
	int num1 = 1;
	int num2 = 1;
	n -= 2;
	if (n <= 0)
	{
		return num2;
	}
	while (n--)
	{
		num1 = num1 + num2;
		num2 = num1 + num2;
	}
	return num2;
}

int DiTui_2(unsigned n)
{
	int num1 = 1;
	int num2 = 2;
	int num3 = 4;
	if (n <= 0)
	{
		return 0;
	}
	else if (n == 1)
	{
		return num1;
	}
	else if (n == 2)
	{
		return num2;
	}
	else if (n == 3)
	{
		return num3;
	}
	else
	{
		n -= 3;
		while (n--)
		{
			num1 = num1 + num2 + num3;
			num2 = num2 + num3 + num1;
			num3 = num3 + num1 + num2;
		}
		return num3;
	}
}
// 奇数在前,偶数在后
void EvenBeforOdd(int *arr, unsigned n)
{
	assert(arr);
	int *start = arr;
	int *end = arr + n - 1;
	while (start < end)
	{
		while (*start % 2 == 1)
		{
			start++;
		}
		while (*end % 2 == 0)
		{
			end--;
		}
		if (start < end)
		{
			swap<int>(*start, *end);
		}
	}
}

int FindLongest(int *arr, unsigned n)
{
	assert(arr);
	if (n == 0)
	{
		return 0;
	}
	int candidate = arr[0];
	unsigned count = 1;
	for (unsigned i = 1; i < n; ++i)
	{
		if (arr[i] == candidate)
		{
			count++;
		}
		else
		{
			count--;
			if (count == 0)
			{
				candidate =	arr[i];
				count = 1;
			}
		}
	}
	return candidate;
}

void FindMetrixNum(int **arr, int M, int N, int &x, int &y, int num)
{
	int curX = 0;
	int curY = N - 1;
	while (curX < M && curY >= 0)
	{
		if (num == arr[curX][curY])
		{
			x = curX;
			y = curY;
			return;
		}
		else if (num > arr[curX][curY]) // 向下走
		{
			curX++;
		}
		else // 向左走
		{
			curY++;
		}
	}
	x = -1;
	y = -1;
	
}
// 是否要检查是否排好序???
int BinarySearch_2(int *arr, unsigned n, int num)
{
	assert(arr);
	if (n == 0)
	{
		return -1;
	}
	unsigned start = 0;
	unsigned end = n - 1;
	while (start <= end)
	{
		// 没有考虑可能溢出情况
		// unsigned middle = start + (end - start) / 2;
		// unsigned middle = start + ((end - start) >> 2);
		unsigned middle = (start + end) / 2;
		int tmp = arr[middle];
		// 倒没有认真考虑数组中相等的情况是最少的。。。
		// 可以考虑!!!
		if (tmp == num)
		{
			return int(middle);
		}
		else if (tmp < num)
		{
			start = middle + 1;
		}
		else 
		{
			end = middle - 1;
		}
	}
	return -1;
}


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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值