POJ 3320 Jessica‘s Reading Problem(哈希、尺取法)

http://poj.org/problem?id=3320

题意:
给出一串数字,要求包含所有数字的最短长度。

 

思路:

哈希一直不是很会用,这道题也是参考了别人的代码,想了很久。

 1 #include<iostream>
 2 #include<algorithm>
 3 #include<string>
 4 #include<cstring>
 5 using namespace std;
 6 
 7 const int PRIME = 99999;
 8 
 9 int n;
10 int len;
11 
12 //开散列法,也就是用链表来存储,所以下面的len是从PRIME开始的,因为前面的都是头结点。
13 
14 struct node       //key是数值大小,num是该key出现的次数,因为是链表存储,所以next指向下一个结点
15 {
16     int key;
17     int num;
18     int next;
19 }p[1000005];
20 
21 int a[1000005];
22 
23 int _hash(int num)
24 {
25     int k = num%PRIME;     //取余
26     while (p[k].next != -1)    //该数值已经出现过了
27     {
28         if (num > p[p[k].next].key)  break;      //按递减的方式排列
29         else if (num == p[p[k].next].key)  return p[k].next;   //如果已经出现过了,直接返回
30         k = p[k].next;
31     }
32     //没有出现过,添加新的结点
33     p[len].key = num;
34     p[len].num = 0;
35     p[len].next = p[k].next;
36     p[k].next = len;
37     len++;
38     return len - 1;
39 }
40 
41 int main()
42 {
43     //freopen("D:\\txt.txt", "r", stdin);
44     while (~scanf("%d", &n) && n)
45     {
46         for (int i = 0; i < PRIME; i++)
47             p[i].next = -1;
48         len = PRIME;
49         int left = 0;
50         int ans;
51         for (int i = 0; i < n; i++)
52         {
53             scanf("%d", &a[i]);
54             int temp = _hash(a[i]);
55             p[temp].num++;
56             if (p[temp].num == 1)   //说明第一次出现,所以肯定要包括进去,此时ans肯定等于i-left+1
57             {
58                 ans = i - left + 1;
59                 continue;
60             }
61             //如果之前已经出现过
62             temp = _hash(a[left]);
63             //如果left指向的数值后面还有出现,那么可以右移一位
64             while (left<n - 1 && p[temp].num>1)
65             {
66                 p[temp].num--;
67                 left++;
68                 temp = _hash(a[left]);
69             }
70             if (ans > i - left + 1)      ans = i - left + 1;
71         }
72         printf("%d\n", ans);
73     }
74     return 0;
75 }

 

接下来再附上尺取法的做法,主要思路和上面是差不多的。

 1 #include<iostream>
 2 #include<algorithm>
 3 #include<string>
 4 #include<cstring>
 5 #include<set>
 6 #include<map>
 7 using namespace std;
 8 
 9 const int maxn = 1000000 + 5;
10 
11 int n;
12 int x[maxn];
13 set<int> p;
14 map<int, int> q;
15 
16 int main()
17 {
18     //freopen("D:\\txt.txt", "r", stdin);
19     while (~scanf("%d", &n))
20     {
21         p.clear();
22         q.clear();
23         for (int i = 1; i <= n; i++)
24         {
25             scanf("%d", &x[i]);
26         }
27 
28         for (int i = 1; i <= n; i++)
29             p.insert(x[i]);
30 
31         int ans = n;
32         int total = p.size();    //不重复的数
33         int sum = 0;
34         int left = 1, right = 1;
35         while (left<=n && right <= n)
36         {
37             if (q[x[right]] == 0)  sum++; //这个数没有出现过
38             q[x[right]]++;
39             
40             while (q[x[left]] > 1)
41             {
42                 q[x[left]]--;
43                 left++;
44             }
45             if (sum == total)
46             {
47                 ans = min(ans, right - left + 1);
48                 if (q[x[left]] == 1)  sum--;
49                 q[x[left]]--;
50                 left++;
51             }
52             right++;
53         }
54         printf("%d\n", ans);
55     }
56     return 0;
57 }

 

posted @ 2017-03-19 23:30  Kayden_Cheung  阅读(206)  评论(0编辑  收藏  举报
//目录