Careercup - Microsoft面试题 - 23123665

2014-05-12 07:44

题目链接

原题:

Given an array having 16000 unique integers, each lying within the range 1<x<20000, how do u sort it. U can load only 1000 numbers at a time in memory.

题目:一个数组里有16000个不重复的整数,所有元素都在1和20000之间。如果你一次至多能在内存里放1000个整数,你要如何排序整个数组?

解法1:这个题目表述是不是有问题?数组本身就是内存的数据吧?内存装不下还叫数组?既然所有元素都是不重复的,就可以用位向量了。用位向量标记,就可以通过一次扫描来排序所有元素了。如果按照一个整数4字节的话,1000个整数有4000字节,总共32000个位,是足够覆盖数据范围的。如果按照16位整数来算,这个算法就不可行了。《编程珠玑》和《Cracking the Coding Interview》上都有类似的题目。内存限制是任何时候都要考虑的实际问题。如果资源总是无限的,这个世界也就没问题需要解决了。

代码:

 1 // http://www.careercup.com/question?id=23123665
 2 // all numbers are unique.
 3 #include <cstdio>
 4 #include <cstring>
 5 using namespace std;
 6 
 7 int main()
 8 {
 9     const int MAXN = 20000;
10     FILE *fin, *fout;
11     unsigned bit[MAXN >> 5];
12     int i;
13     
14     memset(bit, 0, MAXN / 8);
15     
16     fin = fopen("in.txt", "r");
17     while (!feof(fin)) {
18         fscanf(fin, "%u", &i);
19         bit[i >> 5] |= (1 << (i & 31));
20     }
21     fclose(fin);
22     fin = nullptr;
23     
24     fout = fopen("out.txt", "w");
25     for (i = 0; i < MAXN; ++i) {
26         if (bit[i >> 5] & (1 << (i & 31))) {
27             fprintf(fout, "%u\n", i);
28         }
29     }
30     fclose(fout);
31     fout = nullptr;
32     
33     return 0;
34 }

解法2:如果元素存在重复的话,就不能用位向量了。可以用数组来分段统计每个数据范围元素出现的个数,这样能通过多次扫描达到排序的效果。

代码:

 1 // http://www.careercup.com/question?id=23123665
 2 // may contain duplicates.
 3 #include <cstdio>
 4 #include <cstdlib>
 5 #include <cstring>
 6 using namespace std;
 7 
 8 int main()
 9 {
10     const int MAXN = 20000;
11     const int n = 1000;
12     FILE *fin, *fout;
13     int count[n];
14     int i, j;
15     int offset;
16     
17     fin = fopen("in.txt", "r");
18     fout = fopen("out.txt", "w");
19     if (fin == nullptr || fout == nullptr) {
20         printf("File doesn't exist.\n");
21         exit(1);
22     }
23     
24     offset = 0;
25     while (offset < MAXN) {        
26         memset(count, 0, n * sizeof(int));
27         
28         fseek(fin, 0, SEEK_SET);
29         while (!feof(fin)) {
30             fscanf(fin, "%d", &i);
31             if (i >= offset && i < offset + n) {
32                 ++count[i - offset];
33             }
34         }
35         
36         for (i = 0; i < n; ++i) {
37             for (j = 0; j < count[i]; ++j) {
38                 fprintf(fout, "%d\n", i + offset);
39             }
40         }
41         
42         offset += n;
43     }
44     fclose(fin);
45     fin = nullptr;
46     fclose(fout);
47     fout = nullptr;
48     
49     return 0;
50 }

 

转载于:https://www.cnblogs.com/zhuli19901106/p/3722708.html

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

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值