您的位置:首页 > 其它

堆排序,用一种清新脱俗的方式

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;
}

}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: