堆排序,用一种清新脱俗的方式
2017-07-20 09:46
330 查看
最近用OC写算法时遇到这么一道题:
问题:给定一个字符数组,判断字符数组中是否所有的字符只出现过一次,如果是,那么返回yes,否则返回no。
第一种解法很简单,我们通过开辟空间创建Hash表比较即可,代码如下:
BOOL detectString(char *str){
NSUInteger len = strlen(str);
int hash[256] = {0};
for (int i =0; i<len; i++) {
if (hash[str[i]] != 0) {
return NO;
} else {
hash[str[i]]++;
}
}
return YES;
}代码是最基本的C语言代码。可能有些小白会问为什么要开辟256大小的空间呢?这个可以查看下ASCII码中字符的编码即可明白。
当然,以上这种方法不是我要记录的内容,当把这道题进行延伸,说在空间复杂度为O(1)的情况下,如何能够使得时间复杂度最小呢?(也就是不去开辟空间)。要想比较,那么只能通过将字符数组进行排序,比较相邻的字符是否相同来解决。这样就把问题转化道了排序算法上,选取一个空间复杂度为O(1),时间复杂度最低的算法,那就是本文的主角堆排序算法。下面就把这种清新脱俗的堆排序算法贴上来,代码如下:
/**
建立一个堆
@param str 传入的字符串数组
@param i 插入到第几个位置
*/
void heapInsert(char *str,NSUInteger i);
//交换两个值
void swap(char *str,NSUInteger i,NSUInteger j);
void heapify(char *str,NSUInteger i, NSUInteger size); //排序调整
//方法二
BOOL detectString2(char *str){
NSUInteger len = strlen(str);
char newStr[len];
strcpy(newStr, str);
//建立堆
for (NSUInteger i=0; i<len; i++) {
heapInsert(newStr, i);
}
// 排序调整
for (NSUInteger i = len-1; i>0; i--) {
swap(newStr, 0, i);
heapify(newStr, 0, i);
}
//判断是否有重复字符出现
for (NSUInteger i = 1; i<len; i++) {
if (newStr[i] == newStr [i-1]) {
return NO;
}
}
return YES;
}
//建立堆
void heapInsert(char *str,NSUInteger i) {
NSUInteger parent = 0;
while (i != 0) {
parent = (i-1)/2;
if (str[parent] < str[i]) {
swap(str, parent, i);
i = parent;
} else {
break;
}
}
}
//交换节点
void swap(char *str,NSUInteger i,NSUInteger j) {
char temp = str[i];
str[i] = str[j];
str[j] = temp;
}
堆排序
void heapify(char *str,NSUInteger i, NSUInteger size) {
NSUInteger left = i*2+1;
NSUInteger right = i*2+2;
NSUInteger largest = i;
while (left < size) {
if (str[left] > str[i]) {
largest = left;
}
if (right < size && str[right] > str[left]) {
largest = right;
}
if (largest != i) {
swap(str, i, largest);
} else {
break;
}
i = largest;
left = i*2+1;
right = i*2+2;
}
}
问题:给定一个字符数组,判断字符数组中是否所有的字符只出现过一次,如果是,那么返回yes,否则返回no。
第一种解法很简单,我们通过开辟空间创建Hash表比较即可,代码如下:
BOOL detectString(char *str){
NSUInteger len = strlen(str);
int hash[256] = {0};
for (int i =0; i<len; i++) {
if (hash[str[i]] != 0) {
return NO;
} else {
hash[str[i]]++;
}
}
return YES;
}代码是最基本的C语言代码。可能有些小白会问为什么要开辟256大小的空间呢?这个可以查看下ASCII码中字符的编码即可明白。
当然,以上这种方法不是我要记录的内容,当把这道题进行延伸,说在空间复杂度为O(1)的情况下,如何能够使得时间复杂度最小呢?(也就是不去开辟空间)。要想比较,那么只能通过将字符数组进行排序,比较相邻的字符是否相同来解决。这样就把问题转化道了排序算法上,选取一个空间复杂度为O(1),时间复杂度最低的算法,那就是本文的主角堆排序算法。下面就把这种清新脱俗的堆排序算法贴上来,代码如下:
/**
建立一个堆
@param str 传入的字符串数组
@param i 插入到第几个位置
*/
void heapInsert(char *str,NSUInteger i);
//交换两个值
void swap(char *str,NSUInteger i,NSUInteger j);
void heapify(char *str,NSUInteger i, NSUInteger size); //排序调整
//方法二
BOOL detectString2(char *str){
NSUInteger len = strlen(str);
char newStr[len];
strcpy(newStr, str);
//建立堆
for (NSUInteger i=0; i<len; i++) {
heapInsert(newStr, i);
}
// 排序调整
for (NSUInteger i = len-1; i>0; i--) {
swap(newStr, 0, i);
heapify(newStr, 0, i);
}
//判断是否有重复字符出现
for (NSUInteger i = 1; i<len; i++) {
if (newStr[i] == newStr [i-1]) {
return NO;
}
}
return YES;
}
//建立堆
void heapInsert(char *str,NSUInteger i) {
NSUInteger parent = 0;
while (i != 0) {
parent = (i-1)/2;
if (str[parent] < str[i]) {
swap(str, parent, i);
i = parent;
} else {
break;
}
}
}
//交换节点
void swap(char *str,NSUInteger i,NSUInteger j) {
char temp = str[i];
str[i] = str[j];
str[j] = temp;
}
堆排序
void heapify(char *str,NSUInteger i, NSUInteger size) {
NSUInteger left = i*2+1;
NSUInteger right = i*2+2;
NSUInteger largest = i;
while (left < size) {
if (str[left] > str[i]) {
largest = left;
}
if (right < size && str[right] > str[left]) {
largest = right;
}
if (largest != i) {
swap(str, i, largest);
} else {
break;
}
i = largest;
left = i*2+1;
right = i*2+2;
}
}
相关文章推荐
- jsp <input type="file"> 清空value值的一种方式
- 设置重复出现的警报的一种方式。
- DLL方式封装MDI子窗体是一种常用的软件开发技术
- for 循环得另外一种方式
- 上传文件至美国服务器的一种提速方式
- 关于text-overflow(一种省略文字的方式)
- [转]数学是一种思考方式
- 通过gradle下载最新依赖包的一种方式
- SWT中定时器的一种特殊实现方式/SWT中线程互访时display.asyncExec/display.syncExec...程序死掉无响应的解决办法
- java 声明静态Map常量的一种简单方式
- 安装 Apache 出现 <OS 10013> 以一种访问权限不允许的方式做了一个访问套接字的尝试
- PostCSS一种来自未来的书写CSS方式
- DSN和DSN-Less两种数据库连接方式哪一种更好?
- apache(OS 10013)以一种访问权限不允许的方式做了一个访问套接字的尝试 ...
- 按位或运算的一种应用方式
- 关于Operation not allowed after ResultSet closed错误的一种解决方式
- 艾伟也谈项目管理,一种适用于真实世界BPM的协作方式
- 一种经典的邻接表的实现和遍历方式
- Android中实现短信发送的一种方式
- 图片墙的一种实现方式