0
点赞
收藏
分享

微信扫一扫

<力扣刷题>937. 重新排列日志文件

火热如冰 2022-05-03 阅读 32

前言


一、题:重新排列日志文件

给你一个日志数组 logs。每条日志都是以空格分隔的字串,其第一个字为字母与数字混合的 标识符 。

  • 有两种不同类型的日志:

    • 字母日志:除标识符之外,所有字均由小写字母组成
    • 数字日志:除标识符之外,所有字均由数字组成
  • 请按下述规则将日志重新排序:

    • 所有 字母日志 都排在 数字日志 之前。
    • 字母日志 在内容不同时,忽略标识符后,按内容字母顺序排序;在内容相同时,按标识符排序。
    • 数字日志 应该保留原来的相对顺序。
  • 返回日志的最终顺序。

示例 1:

输入:logs = ["dig1 8 1 5 1","let1 art can","dig2 3 6","let2 own kit dig","let3 art zero"]
输出:["let1 art can","let3 art zero","let2 own kit dig","dig1 8 1 5 1","dig2 3 6"]
解释:
字母日志的内容都不同,所以顺序为 "art can", "art zero", "own kit dig"
数字日志保留原来的相对顺序 "dig1 8 1 5 1", "dig2 3 6"

示例 2:

输入:logs = ["a1 9 2 3 1","g1 act car","zo4 4 7","ab1 off key dog","a8 act zoo"]
输出:["g1 act car","a8 act zoo","ab1 off key dog","a1 9 2 3 1","zo4 4 7"]

二、方法

  • 先遍历一遍数组,将所有字母日志加入数组中,按规则排序:
  • 在遍历一遍数组,将数字日志加在后面;
    • 比较时,先将数组日志按照第一个空格分成两部分字符串,其中第一部分为标识符。第二部分的首字符可以用来判断该日志的类型。两条日志进行比较时,需要先确定待比较的日志的类型,然后按照以下规则进行比较:
    • 字母日志始终小于数字日志。
    • 数字日志保留原来的相对顺序。当使用稳定的排序算法时,可以认为所有数字日志大小一样。当使用不稳定的排序算法时,可以用日志在原数组中的下标进行比较。
    • 字母日志进行相互比较时,先比较第二部分的大小;如果相等,则比较标识符大小。比较时都使用字符串的比较方式进行比较。

代码:

/**
* Note: The returned array must be malloced, assume caller calls free().
*/

bool is_letter(char *str) {
char *cp = strchr(str, ' ') + 1;
return *cp >= 'a' & 'z';
}

int comp(const void *p1, const void *p2) {
char *s1 = *(char **) p1;
char *s2 = *(char **) p2;
// 找到指向第一个空格字符的指针
char *space1 = strchr(s1, ' ');
char *space2 = strchr(s2, ' ');
// 将字符串截成两段
*space1 = '\0';
*space2 = '\0';
// 分别得到 标识 和 内容的排序结果
int comp_tag = strcmp(s1, s2);
int comp_con = strcmp(space1 + 1, space2 + 1);
// 还原字符串
*space1 = ' ';
*space2 = ' ';
return comp_con != 0 ? comp_con : comp_tag;
}

char **reorderLogFiles(char **logs, int logsSize, int *returnSize){
char **res = (char **) malloc(logsSize * sizeof(char *));
*returnSize = 0;
for (int i = 0; i < logsSize; i++) {
if (is_letter(logs[i])) {
res[(*returnSize)++] = logs[i];
}
}
qsort(res, *returnSize, sizeof(char *), comp);
for (int i = 0; i < logsSize; i++) {
if (!is_letter(logs[i])) {
res[(*returnSize)++] = logs[i];
}
}
return res;
}


C语言函数:qsort()

  • 头文件: #include <stdlib.h>,其时间复杂度为 O(nlogn)。函数原型如下:
void qsort(void *base, size_t nmemb, size_t size, int (*compar)(const void *, const void *));

  • 此函数需要四个参数。
    • 第一个参数是需要排序的数组的基地址,因为是 void * 类型,所以此函数可以给任何类型的数组进行排序
    • 第二个参数是待排序的数量(size_t 是一种特别的数据类型,可以近似理解为 int 型);
    • 第三个是单个数组元素的大小,即字节数,例如 int 型就是 4 或者 sizeof(int) (sizeof 的返回值类型就是 sizeof)char 型就是 1 或者sizeof(char)。因为为了适用于各种数据结构,第一个参数将指向数组的指针强转成了 void * 类型,也即此时函数并不知道将要进行排序的数组内存储的是什么元素,因此我们需要显式地告诉它单个元素所占的长度;
    • 第四个参数是一个指向函数的指针,其作用是规定排序的规则,即按照什么样的方式进行排序。

下面我们对一个整型数组排序为例:

#include<stdio.h>
#include<stdlib.h>

//比较函数原型
int mycmp(const void* p1, const void* p2);

int main() {

int num[10] = {32, -4, 89, 232, 2, 12, -32, 0, -4, 89};

qsort(num, 10, sizeof(int), mycmp);

for(int i=0; i<10; i++)
printf("%d ", num[i]);

printf("\n");
return 0;
}

//比较函数
int mycmp(const void* p1, const void* p2){
const int * a = (const int *) p1;
const int * b = (const int *) p2;

int value = 0;

if(*a < *b)
value = -1;
else if(*a == *b)
value = 0;
else value = 1;

return value;
}

运行结果为:

在这里插入图片描述

举报

相关推荐

0 条评论