- 浏览: 724681 次
- 性别:
- 来自: 北京
最新评论
-
wxweven:
Surmounting 写道既然 Java 的跳表那么少,我决 ...
SkipList 跳表 -
暮雪云然:
写的不错,很透彻
Java静态内部类 -
bzhao:
好,赞扬!
Linux信号详解 -
jacktao219:
赞一个~! ,现在正在看redis 所以接触到跳表
SkipList 跳表 -
is_leon:
vote--后还要判断是否为0吧,如果为0则废掉重新置位can ...
现在有一个整数数组,已知一个数出现的次数超过了一半,请用O(n)的复杂度的算法找出这个数
算法过程:
1 将顶点按x坐标递增排序,若x相同,按y坐标递增排序,然后枚举所有边,对每一条由点p1和p2(根据排序p1 < p2)组成的边按照如下方式可唯一确定一个正方形:
1) 将边绕p1逆时针旋转90度得到点p3
2) 将边绕p2顺时针旋转90度得到点p4
则p1 p2 p3 p4组成一个正方形,设p1 = (x1,y1), p2 = (x2, y2),根据向量的旋转公式可以求出p3, p4的坐标为
p3 = (y1 - y2 + x1, x2 - x1 + y1)
p4 = (y1 - y2 + x2, x2 - x1 + y2)
2 然后搜索点p3和p4是否存在,若存在则找到一个正方形,计数加1,可以发现总是存在两条边确定的正方形是一样的,也就是说每个正方形会被发现2次,所以要将最后的计数结果除以2.
实现的时候关键是如何搜索某个点是否存在,由于所有点都排序过,所以可以用二分查找来搜索,但速度比较慢,至少1000ms, hash的速度更快些,可以达到几百ms,还有hash表如果用开放地址线性探测法解决冲突的话,很容易超时,
而用链地址法解决冲突效果要好很多。下面是二分搜索和hash两种方法的代码实现。
二分查找
#include <stdio.h> #include <string.h> //#define DEBUG #ifdef DEBUG #define debug(...) printf( __VA_ARGS__) #else #define debug(...) #endif #define N 1000 struct Point { int x; int y; }; struct Point point[N]; int n; /* 点的个数 */ /* 由于点已经按照坐标排序过,所以采用二分查找 * 搜索点(x,y)是否存在,存在返回1,否则返回0 */ int bsearch(int x, int y) { int m, s, t; s = 0; t = n-1; while (s <= t) { m = (s+t)/2; if (point[m].x == x && point[m].y == y) return 1; if (point[m].x > x || (point[m].x == x && point[m].y > y)) { t = m-1; } else { s = m+1; } } return 0; } int main() { int x, y, i, j, count; while (scanf("%d", &n), n) { count = 0; for (i = 0; i < n; i++) { scanf("%d %d", &x, &y); //插入法对点排序,按照x从小到大,y从小到大,且x优先排列的方式 for (j = i-1; j >= 0; j--) { if (point[j].x > x || (point[j].x == x && point[j].y > y)) { point[j+1] = point[j]; } else { break; } } point[j+1].x = x; point[j+1].y = y; } /* 枚举所有边,对每条边的两个顶点可以 * 确定一个唯一的正方形,并求出另外两个顶点的坐标 */ for (i = 0; i < n; i++) { for (j = (i+1); j < n; j++) { //计算第三个点的坐标,搜索其是否存在 x = point[i].y-point[j].y+point[i].x; y = point[j].x-point[i].x+point[i].y; if (bsearch(x,y) == 0) { continue; } //计算第四个点的坐标,搜索其是否存在 x = point[i].y-point[j].y+point[j].x; y = point[j].x-point[i].x+point[j].y; if (bsearch(x, y)) { count++; } } } printf("%d\n", count/2); } return 0; }
hash
#include <stdio.h> #include <string.h> #include <stdlib.h> #define DEBUG #ifdef DEBUG #define debug(...) printf( __VA_ARGS__) #else #define debug(...) #endif #define N 1000 /* 顶点个数 */ #define M 2999 /* hash表的大小,取素数冲突冲突较少 */ struct Point { int x; int y; }; struct Point point[N]; /* 使用链地址法解决冲突, 表头不存数据 */ struct hash_entry { int x; int y; struct hash_entry *next; }; struct hash_entry hash_table[M+1]; int conflict; void insert(int x, int y) { unsigned int p; struct hash_entry *new_entry; p = (x*x+y*y)%M; /* hash函数 */ //创建一个新的entry new_entry = (struct hash_entry *)malloc(sizeof(struct hash_entry)); new_entry->x = x; new_entry->y = y; /* 把新entry插在最前面,这样,越先插进来的entry在链表的越后面, *最后一个entry的next指针为空 */ new_entry->next = hash_table[p].next; hash_table[p].next = new_entry; } int find(int x, int y) { unsigned int p; struct hash_entry *entry; p = (x*x+y*y)%M; /* hash函数 */ for(entry = hash_table[p].next; entry != 0 && (entry->x != x \ || entry->y != y); entry = entry->next, conflict++); if (entry) { return 1; } return 0; } int main() { int n, x, y, i, j, count; while (scanf("%d", &n), n) { memset(hash_table, 0, sizeof(hash_table)); count = 0; for (i = 0; i < n; i++) { scanf("%d %d", &x, &y); //插入法对点排序,按照x从小到大,y从小到大,且x优先排列的方式 for (j = i-1; j >= 0; j--) { if (point[j].x > x || (point[j].x == x && point[j].y > y)) { point[j+1] = point[j]; } else { break; } } point[j+1].x = x; point[j+1].y = y; insert(x, y); } /* 枚举所有边,对每条边的两个顶点可以 * 确定一个唯一的正方形,并求出另外两个顶点的坐标 */ for (i = 0; i < n; i++) { for (j = (i+1); j < n; j++) { //计算第三个点的坐标,搜索其是否存在 x = point[i].y-point[j].y+point[i].x; y = point[j].x-point[i].x+point[i].y; if (!find(x, y)) { continue; } //计算第四个点的坐标,搜索其是否存在 x = point[i].y-point[j].y+point[j].x; y = point[j].x-point[i].x+point[j].y; if (find(x, y)) { count++; } } } printf("%d\n", count/2); } debug("conflict = %d\n", conflict); return 0; }
发表评论
-
Paxos算法
2012-04-18 10:59 2666分布式系统的核心问题是数据一致性,解决一致性有很多算法,而 P ... -
编程之美3.3 计算字符串的相似度
2012-03-13 23:26 33问题描述 定义一套操作方法, 把两个不相同的字符串变得相同, ... -
编程之美3.1 字符串移位包含的问题
2012-03-12 23:26 3333题目 给定两个字符串 s ... -
SkipList 跳表
2011-10-09 01:08 39805为什么选择跳表 目前经常使用的平衡数据结构有:B树,红黑树, ... -
(转)一致性哈希算法及其在分布式系统中的应用
2011-09-29 19:02 2319原文地址: http://www.cnb ... -
算法导论习题 5.1 -2
2011-09-29 09:23 2009描述random(a, b)过程的一种实现,它只调用rando ... -
现在有一个整数数组,已知一个数出现的次数超过了一半,请用O(n)的复杂度的算法找出这个数
2011-05-05 19:43 6240现在有一个整数数组,已知一个数出现的次数超过了一半,请用O(n ... -
从海量数据中找中位数(c语言实现)
2011-05-05 12:49 5041题目:5亿个int,从中找出第k大的数 算法:之后补上 ... -
寻找最大的K个数 (C语言实现)
2011-05-04 16:31 5352题目:100亿个整数,求最大的1万个数,并说出算法的时间复杂度 ... -
kmp算法的理解与实现
2011-04-30 21:29 25503KMP算法曾被我戏称为看毛片算法,当时笑喷...... ... -
败者树 多路平衡归并外部排序
2011-04-25 21:52 10688一 外部排序的基本思路 ... -
实现两个整数的除法,不能用除号和乘号
2011-04-22 15:17 3642对于两个整数a和b, 求a/b,可以从1开始枚举结果resul ... -
最大公共子字符串(Longest Common Substring)
2011-04-22 13:33 3413Longest Common Substring和Longes ... -
poj 1458 最长公共子串(Longest Common Subsequence)
2011-04-22 10:45 2575LCS问题: 给定序列 X = <x1,x2,... ... -
归并排序
2011-04-21 21:51 1178#include <stdio.h> #i ... -
快速排序 顺序统计量 数组分割
2011-04-21 19:28 1370#include <stdio.h> #in ... -
位运算集锦
2011-04-21 17:15 2113文中2'k代表2的k次方 1 除以2的k次幂可以用位运 ... -
最长递增子序列
2011-04-21 14:45 1191设L = <a1,a2,...an>是n个不同的实 ... -
poj 2774 后缀数组
2011-03-21 17:28 1792#include <stdio.h> # ... -
poj 2823 线段树
2011-03-17 18:49 1623赤裸裸的线段树,数据量很大,加了IO优化函数。 #in ...
相关推荐
- POJ 3373、POJ 1691:二分查找技术的应用。 ### 动态规划 #### 二维动态规划 - **题目示例**: - POJ 1191、POJ 1054:基于矩阵的状态转移方程。 - POJ 3280、POJ 2029:多维状态空间的探索。 #### 递归动态...
快速查找技术如二分查找、哈希等,在数据结构和算法中占有重要地位,能够大大提高程序效率。 #### 题目示例及解析: - **2503** 和 **2513** 两题适合了解快速查找的基本原理。 - **1035** 和 **1200** 这两个题目...
商店价格排名问题可以通过哈希表来快速查找特定商店的价格变化,同时通过排序和二分查找来提高效率。直接使用STL中的map也可以,但可能会较慢。 5. POJ 3087【基础】 本题是关于木片堆叠的问题,可以模拟每次操作并...
4. 二分查找 5. 叉乘、判线段相交、凸包 6. BFS、DFS、hash表 7. 数学上的辗转相除、线段交点、多角形面积公式 数据结构 1. 线段树 2. 并查集 3. 动态规划的各个典型(LCS、最长递增子串、三角剖分、记忆化dp) 4....
- **题目**: 包括字符串处理(`hash`)、树状数组(`poj3253`)等。 - **所需知识**: 字符串处理技术、树状数组的应用以及Trie树等相关数据结构的构建与查询。 ### 二、图论 #### 1. 图的表示与基本操作 - **题目**: ...
PPT可能还介绍了更高效的查找技术,如二分查找。 7. **23KMP和TRIE.ppt** - KMP算法是一种改进的字符串匹配算法,避免了不必要的回溯。而Trie(字典树或前缀树)是一种高效存储字符串集合的数据结构,特别适合于...
根据题目编号,可以推测这是一个关于搜索的问题,可能是关于查找图中某个特定路径或最短路径的问题。 #### 总结 以上就是根据提供的文件信息整理出的一些关于北京大学编程比赛中搜索题目的知识点。这些题目涵盖了...
二分查找是一种高效的搜索方法,适用于有序数组,可以在对数时间内找到目标值。 叉乘用于计算向量的叉积,可用于判断线段是否相交。凸包算法如Graham扫描法,用于找到一组点的最小凸多边形包围。 BFS(广度优先...
4. **二分查找**:在有序数组中查找特定元素,时间复杂度为O(log n)。 5. **叉乘、线段相交与凸包**:在几何问题中常用,如计算点积判断线段是否垂直,以及计算凸包。 6. **BFS(广度优先搜索)与DFS(深度优先...
- **1634**:二分查找的应用,如寻找最接近的目标值。 - **1689**:图论中的经典问题,如最小生成树的构建。 #### 四、综合实战案例 除了以上提到的基础和高级算法外,还有一些题目要求综合运用多种技术点来解决...