标签:
一. 题目
Time Limit: 2000MS | Memory Limit: 65536K | |
Total Submissions: 274040 | Accepted: 48891 |
Description
Input
Output
Sample Input
12 4873279 ITS-EASY 888-4567 3-10-10-10 888-GLOP TUT-GLOP 967-11-11 310-GINO F101010 888-1200 -4-8-7-3-2-7-9- 487-3279
Sample Output
310-1010 2 487-3279 4 888-4567 3
Source
二. 题意
1.电话簿上的电话号码为了方便记忆,并非全用数字表示,有些用字母表示或用 “ - ” 符号分割
2.字母与数字之间存在一定的映射关系,“ - ” 没有实际意义
3. 通过转换后得到统一标准的电话号码,其构成为"xxx-xxxx", 总共由八位字符(七位数字和一个"-")符号构成
5. 现在给定一个电话清单,从中找出重复的电话号码
三. 分析
1. 算法核心: 三种解决方法
1.1 桶排序
1.2 字典树(Trie树)
1.3 快速排序
2. 实现细节:
2.1 桶排序
2.1.1 桶的大小为七位数的上限(10000000)
2.1.2 每个桶存储对应7位数的电话号码出现的次数
2.1.3 将电话号码转换为7位数,递增对应该七位数的桶元素的值
2.1.4 遍历所有桶,得到和输出大于1的所有桶元素
2.1.5 小细节: 字符到数的转换,输出格式的正确转换
2.2 字典树(Trie树)
2.2.1 建立Trie树: 用静态数组存储每个node, 简化代码实现
2.2.2 遍历所有输入电话号码,转换为数字,将该数字插入Trie树
2.2.3 每插入一个完整电话号码,在其最后插入的node中设置两个标记:出现次数 和 完整电话号码的结束标记
2.2.4 深度遍历(dfs)Trie树, 输出所有出现次数大于1的完整电话号码
2.2.5 Trie树的所有child构成为从左到右(0 - 9),遍历的顺序也是如此,从而保证了电话号码的输出顺序也是从小到大
2.3 快速排序
2.3.1 用一个二维字符数组存储所有的电话号码
2.3.2 对该数组进行快速排序
2.3.3 遍历该有序数组,顺序输出大于1的所有电话号码
2.3.4 个人实现算法的宗旨是尽量少用库,能实现的尽量自己实现
2.3.4.1 对于此题,发现如果用自己实现的快速排序,发现会超时
2.3.4.2 换成库的qsort则可以通过
2.3.4.3 分析发现实际上库对于qsort做了很多的优化,并非基本的快排,有时间可以研究一下
2.3.4.4 两个qsort优化的参考文档:
http://blog.chinaunix.net/uid-25510439-id-275436.html
http://blog.csdn.net/insistgogo/article/details/7785038
四. 题解
4.1 桶排序
1 #include <stdio.h> 2 3 #define PHONE_NUMBER 256 4 #define MAX_NUMBER 10000000 5 #define BASE_NUMBER 1000000 6 #define LENGTH_NUMBER 8 7 #define MAP_SIZE (‘Z‘ - ‘A‘ + 1) 8 int map_num[MAP_SIZE] = {2, 2, 2, 3, 3, 3, 4, 4, 4, 9 5, 5, 5, 6, 6, 6, 7, -1, 7, 10 7, 8, 8, 8, 9, 9, 9, -1}; 11 int bucket[MAX_NUMBER]; 12 13 int main() 14 { 15 int i = 0, j = 0, count = 0, nums = 0; 16 17 scanf("%d\n", &count); 18 for (j = 0; j < count; j++) { 19 char phone_number[PHONE_NUMBER]; 20 int tmp = 0; 21 22 scanf("%s\n", phone_number); 23 24 for (i = 0; phone_number[i] != ‘\0‘; i++) { 25 if (‘-‘ == phone_number[i]) continue; 26 tmp = tmp * 10 + 27 ((phone_number[i] >= ‘A‘ && phone_number[i] <= ‘Z‘) ? 28 map_num[phone_number[i] - ‘A‘] : phone_number[i] - ‘0‘); 29 } 30 bucket[tmp]++; 31 } 32 33 for (i = 0; i < MAX_NUMBER; i++) { 34 int b_tmp, base_number = BASE_NUMBER; 35 36 if (bucket[i] < 2) continue; 37 38 b_tmp = i; 39 nums++; 40 41 for (j = 0; j < LENGTH_NUMBER; j++) { 42 if (3 == j) { printf("-"); continue; } 43 printf("%d", b_tmp / base_number); 44 b_tmp %= base_number; 45 base_number /= 10; 46 } 47 printf(" %d\n", bucket[i]); 48 } 49 50 if (0 == nums) printf("No duplicates.\n"); 51 52 return 0; 53 }
4.2 字典树(Trie树)
1 #include <stdio.h> 2 3 #define BASE_NUMBER 1000000 4 #define MAP_SIZE (‘Z‘ - ‘A‘ + 1) 5 #define TRIE_CHILD_CNTS 10 6 #define PHONE_NUMBER 256 7 #define PHONE_NUMBER_LENGTH 7 8 #define BASE_NUMBER 1000000 9 10 int map_num[MAP_SIZE] = {2, 2, 2, 3, 3, 3, 4, 4, 4, 11 5, 5, 5, 6, 6, 6, 7, -1, 7, 12 7, 8, 8, 8, 9, 9, 9, -1}; 13 int tree_index = 0; 14 int is_duplicated = 0; 15 16 typedef struct Trie { 17 int is_word; 18 int word_cnts; 19 struct Trie* childs[TRIE_CHILD_CNTS]; 20 } trie_tree_t; 21 22 trie_tree_t trie_nodes[BASE_NUMBER]; 23 24 void new_trie_tree(int index) { 25 int i; 26 trie_nodes[index].is_word = 0; 27 trie_nodes[index].word_cnts = 0; 28 for (i = 0; i < TRIE_CHILD_CNTS; i++) trie_nodes[index].childs[i] = NULL; 29 } 30 31 void add_trie_node(int num) { 32 int i, j, base_number = BASE_NUMBER; 33 trie_tree_t* tree = &trie_nodes[0]; 34 35 for (i = 0; i < PHONE_NUMBER_LENGTH; i++) { 36 j = num / base_number; 37 num %= base_number; 38 base_number /= 10; 39 if (NULL == tree->childs[j]) { 40 new_trie_tree(++tree_index); 41 tree->childs[j] = &trie_nodes[tree_index]; 42 } 43 tree = tree->childs[j]; 44 } 45 46 tree->is_word = 1; 47 tree->word_cnts++; 48 } 49 50 void dfs(int phone_number[PHONE_NUMBER_LENGTH], int number_index, trie_tree_t *tree_p) 51 { 52 int i; 53 if (tree_p->is_word && 1 < tree_p->word_cnts) { 54 for (i = 0; i < PHONE_NUMBER_LENGTH; i++) { 55 if (3 == i) printf("-"); 56 57 printf("%d", phone_number[i]); 58 } 59 60 printf(" %d\n", tree_p->word_cnts); 61 is_duplicated = 1; 62 } 63 64 for (i = 0; i < TRIE_CHILD_CNTS; i++) { 65 if (tree_p->childs[i] && number_index < PHONE_NUMBER_LENGTH) { 66 phone_number[number_index] = i; 67 dfs(phone_number, number_index + 1, tree_p->childs[i]); 68 } 69 } 70 } 71 72 int main() 73 { 74 int i = 0, j = 0, tmp = 0, count = 0; 75 int number[PHONE_NUMBER_LENGTH]; 76 77 scanf("%d\n", &count); 78 for (j = 0; j < count; j++) { 79 char phone_number[PHONE_NUMBER]; 80 int tmp = 0; 81 scanf("%s\n", phone_number); 82 83 for (i = 0; phone_number[i] != ‘\0‘; i++) { 84 if (‘-‘ == phone_number[i]) continue; 85 tmp = tmp * 10 + 86 ((phone_number[i] >= ‘A‘ && phone_number[i] <= ‘Z‘) ? 87 map_num[phone_number[i] - ‘A‘] : phone_number[i] - ‘0‘); 88 } 89 90 add_trie_node(tmp); 91 } 92 93 dfs(number, 0, &trie_nodes[0]); 94 95 if (0 == is_duplicated) printf("No duplicates.\n"); 96 97 return 0; 98 }
4.3 快速排序
1 #include <stdio.h> 2 #include <stdlib.h> 3 #include <string.h> 4 5 #define PHONE_NUMBER 256 6 #define MAX_NUMBERS 100000 7 #define LENGTH_NUMBER 9 8 #define MAP_SIZE (‘Z‘ - ‘A‘ + 1) 9 #define SEP_INDEX 3 10 11 #define CUSTOM 0 12 #define USING_POINTER_FOR_COMPARE 0 13 14 char map_num[MAP_SIZE] = {‘2‘, ‘2‘, ‘2‘, ‘3‘, ‘3‘, ‘3‘, ‘4‘, ‘4‘, ‘4‘, 15 ‘5‘, ‘5‘, ‘5‘, ‘6‘, ‘6‘, ‘6‘, ‘7‘, ‘-1‘, ‘7‘, 16 ‘7‘, ‘8‘, ‘8‘, ‘8‘, ‘9‘, ‘9‘, ‘9‘, ‘-1‘}; 17 18 char numbers[MAX_NUMBERS][LENGTH_NUMBER]; 19 20 #if USING_POINTER_FOR_COMPARE 21 char *p_numbers[MAX_NUMBERS]; 22 #endif 23 24 int is_duplicate = 0; 25 26 int mystrcmp(const char *str1, const char *str2) 27 { 28 while (*str1 == *str2) { 29 if (*str1 == ‘\0‘) return 0; 30 str1++; str2++; 31 } 32 33 return *str1 - *str2; 34 } 35 36 #if CUSTOM 37 38 #if USING_POINTER_FOR_COMPARE 39 40 void quicksort(char *A[], int left, int right, int(*func)(const char*, const char*)) { 41 int i = left, j = right; 42 char *t, *tmp; 43 tmp = A[i]; 44 45 if (i > j) return; 46 47 while (i != j) { 48 while (func(tmp, A[j]) <= 0 && i < j) j--; 49 while (func(A[i], tmp) <= 0 && i < j) i++; 50 51 if (i < j) { 52 t = A[i]; 53 A[i] = A[j]; 54 A[j] = t; 55 } 56 } 57 A[left] = A[i]; 58 A[i] = tmp; 59 60 quicksort(A, left, i - 1, func); 61 quicksort(A, i + 1, right, func); 62 } 63 64 #else 65 66 void mystrcpy(char *str1, const char *str2) 67 { 68 while (*str2 != ‘\0‘) { 69 *str1 = *str2; 70 str1++; str2++; 71 } 72 73 *str1 = ‘\0‘; 74 } 75 76 void quicksort(char A[][LENGTH_NUMBER], int left, int right, int(*func)(const char*, const char*)) { 77 int i = left, j = right; 78 char t[LENGTH_NUMBER], tmp[LENGTH_NUMBER]; 79 mystrcpy(tmp, A[i]); 80 81 if (i > j) return; 82 83 while (i != j) { 84 while (func(tmp, A[j]) <= 0 && i < j) j--; 85 while (func(A[i], tmp) <= 0 && i < j) i++; 86 87 if (i < j) { 88 mystrcpy(t, A[i]); 89 mystrcpy(A[i], A[j]); 90 mystrcpy(A[j], t); 91 } 92 } 93 mystrcpy(A[left], A[i]); 94 mystrcpy(A[i], tmp); 95 96 quicksort(A, left, i - 1, func); 97 quicksort(A, i + 1, right, func); 98 } 99 100 #endif 101 102 #endif 103 104 int sort_function(const void *a,const void *b) 105 { 106 return(strcmp((char*)a,(char*)b)); 107 } 108 109 int main() 110 { 111 int i = 0, j = 0, count = 0, nums = 1, number_index = 0; 112 113 scanf("%d\n", &count); 114 for (j = 0; j < count; j++) { 115 char phone_number[PHONE_NUMBER]; 116 117 scanf("%s\n", phone_number); 118 119 for (i = 0; phone_number[i] != ‘\0‘; i++) { 120 if (‘-‘ == phone_number[i]) continue; 121 if (SEP_INDEX == number_index) numbers[j][number_index++] = ‘-‘; 122 numbers[j][number_index++] = ((phone_number[i] >= ‘A‘ && phone_number[i] <= ‘Z‘) ? 123 map_num[phone_number[i] - ‘A‘] : phone_number[i]); 124 } 125 number_index = 0; 126 127 #if USING_POINTER_FOR_COMPARE 128 p_numbers[j] = numbers[j]; 129 #endif 130 131 } 132 133 #if CUSTOM 134 quicksort(p_numbers, 0, count - 1, mystrcmp); 135 136 #if USING_POINTER_FOR_COMPARE 137 138 for (j = 0; j < count - 1; j++) { 139 if (0 == mystrcmp(p_numbers[j], p_numbers[j + 1])) { 140 is_duplicate = 1; 141 nums++; 142 } else { 143 if (1 < nums) printf("%s %d\n", p_numbers[j], nums); 144 nums = 1; 145 } 146 } 147 148 if (1 < nums) printf("%s %d\n", p_numbers[j], nums); 149 150 #else 151 152 for (j = 0; j < count - 1; j++) { 153 if (0 == mystrcmp(numbers[j], numbers[j + 1])) { 154 is_duplicate = 1; 155 nums++; 156 } else { 157 if (1 < nums) printf("%s %d\n", numbers[j], nums); 158 nums = 1; 159 } 160 } 161 162 if (1 < nums) printf("%s %d\n", numbers[j], nums); 163 164 #endif 165 166 167 #else 168 169 qsort(numbers, count, LENGTH_NUMBER, sort_function); 170 171 for (j = 0; j < count - 1; j++) { 172 if (0 == mystrcmp(numbers[j], numbers[j + 1])) { 173 is_duplicate = 1; 174 nums++; 175 } else { 176 if (1 < nums) printf("%s %d\n", numbers[j], nums); 177 nums = 1; 178 } 179 } 180 181 if (1 < nums) printf("%s %d\n", numbers[j], nums); 182 183 #endif 184 185 if (0 == is_duplicate) printf("No duplicates.\n"); 186 187 return 0; 188 }
[POJ] #1003# 487-3279 : 桶排序/字典树(Trie树)/快速排序
标签:
原文地址:http://www.cnblogs.com/yuanzone/p/5503408.html