第三题找不到很好的解决方案。搜索+剪枝但感觉复杂度太吓人;DP状态太多,内存会爆掉;数学方法 ---- 整数拆分,想不出怎么拆;... 。等候大牛们指点迷津。
感觉这次的试题有一定难度,也很繁琐。
1,实现void strtol(char* num_str,char** endptr,int base)函数,此函数的功能是将一个字符串num_str转换成整数。num_str中保存的是待转换的字符串。字符串有8,10,16进制三种形式,保存在base参数中,若base为0,则需要自己判断具体的进制。要判断是否溢出,若为上溢出,返回INT_MAX,若为下溢出,返回INT_MIN。字符串num_str可能存在非法字符,若存在非法字符,返回非法字符前面的转换结果,并将endptr指向第一个非法字符,若没有非法字符,不需要返回endptr。
#注:不能使用任何库函数。
思路:在 base == 0 时判断进制,读数时注意非法字符,就这两点。
程序:
#include <iostream>
using namespace std;
/*
* 判断进制
* 1. num_str中的字符都不大于 '7' 则返回 8 进制
* 2. num_str中的字符都不大于 '9' 则返回 10 进制
* 3. 返回 16 进制
*/
int find_base(char *num_str)
{
char c = '0';
for (char *temp = num_str; *temp != '/0'; ++temp)
{
if ((*temp >= '0' && *temp <= '9')
|| (*temp >= 'a' && *temp <= 'f') || (*temp >= 'A' && *temp <= 'F'))
{
c = (*temp > c ? *temp: c);
}
else
{
break;
}
}
if (c <= '7') return 8;
else if (c <= '9') return 10;
return 16;
}
bool check(char c, int base)
{
switch(base)
{
case 8:
return (c >= '0' && c <= '7');
case 10:
return (c >= '0' && c <= '9');
case 16:
return ((c >= '0' && c <= '9') || (c >= 'a' && c <'f')
|| (c >= 'A' && c <= 'F'));
default:
return false;
}
return false;
}
int char_to_int(char c, int base)
{
if (base <= 10 || c <= '9')
return (c - '0');
if ((c >= 'a' && c <= 'f') )
return (c - 'a' + 10);
return (c - 'A' + 10);
}
int str_to_int(char *num_str, char **endptr, int base)
{
__int64 sum = 0;
int sign = 1;
if (num_str[0] == '-')
{
sign = -1;
++num_str;
}
for (; *num_str != '/0'; ++num_str)
{
if (!check(*num_str, base))
{
*endptr = num_str;
break;
}
sum = sum * base + char_to_int(*num_str, base);
if ((sign == 1) && sum >= INT_MAX)
return INT_MAX;
else if (sign == -1 && sum >= -INT_MIN)
{
return INT_MIN;
}
}
return (int)sum;
}
int strtol(char *num_str, char **endptr, int base)
{
if (base == 0)
{
base = find_base(num_str[0] == '-' ? (num_str + 1): num_str);
}
return str_to_int(num_str, endptr, base);
}
int main()
{
char *endptr = NULL;
char *num_str = "-A0W000000";
int base = 16;
int ans = strtol(num_str, &endptr, base);
return 0;
}
2,从1亿个数中,找出最大的1000个数。效率要尽可能的高,使用的额外空间要尽可能小。
void max_num(int* source_num,int* max_num)
source_num:数组包括所有的1亿个数。
max_num:保存最大的1000个数。
#注:不能使用任何库函数。
思路:维护一个有1000个元素的最小堆即可。
比较下一个元素与堆中的最小值,大于则heap_pop(), 再heap_push()。
最后堆中的1000个元素即为答案。
程序:
#include <stdio.h>
const int MAX_NUM = 5;
const int MAX_SRC = 10;
void swap(int &x, int &y)
{
int temp = x;
x = y;
y = temp;
}
void heap_fix_down(int root, int *max_num, int size)
{
int min_index = root;
int left = (root << 1) + 1;
int right = left + 1;
if (left < size && max_num[min_index] > max_num[left])
min_index = left;
else if (right < size && max_num[min_index] > max_num[right])
min_index = r[right]
if (min_index != root)
{
swap(max_num[min_index], max_num[root]);
heap_fix_down(min_index, max_num, size);
}
}
void heap_fix_up(int *max_num, int size)
{
size = size - 1;
while (size > 0)
{
int p = (size - 1) >> 1;
if (max_num[size] < max_num[p])
{
swap(max_num[size], max_num[p]);
size = p;
}
else
break;
}
}
void heap_pop(int *max_num, int& size)
{
max_num[0] = max_num[--size];
heap_fix_down(0, max_num, size);
}
void heap_push(int val, int *max_num, int& size)
{
max_num[size++] = val;
heap_fix_up(max_num, size);
}
void max_1000num(int *source_num, int *max_num)
{
int i, size = 0;
for (i = 0; i < MAX_NUM; ++i)
{
heap_push(source_num[i], max_num, size);
}
for (i = MAX_NUM; i < MAX_SRC; ++i)
{
if (max_num[0] < source_num[i])
{
heap_pop(max_num, size);
heap_push(source_num[i], max_num, size);
}
}
}
int main()
{
int source_num[MAX_SRC] = {100, 50, 10, 11, 3, 9, 13, 55, 77, 99};
int max_num[MAX_NUM];
max_1000num(source_num, max_num);
return 0;
}
3,若对于整数N,在集合{1,2……,N}中找出m个数,使其和等于剩下的N-m个数的和。返回所有可能的组合数。N<10000。
#注:不能使用任何库函数。