#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;
}