Warning: file_get_contents(/data/phpspider/zhask/data//catemap/3/arrays/12.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Arrays O(n)就地压缩算法;“相同字母模式”;_Arrays_C_Time Complexity - Fatal编程技术网

Arrays O(n)就地压缩算法;“相同字母模式”;

Arrays O(n)就地压缩算法;“相同字母模式”;,arrays,c,time-complexity,Arrays,C,Time Complexity,这是我在这里的第一篇文章,所以我希望我能遵守规则。 几天前我参加了一次工作面试,我遇到了一个我能解决的问题(直到现在)。 想法是(在C上,但我想它不是isuue):给定一个长度为n的字符*,您应该使用O(1)内存comp(就地更改),并将相同字符的模式压缩为“num+char”,其中num是模式长度,char是模式的字符。您可以假设内存足够长,可以包含预期的结果。预期时间补偿为O(n) 示例-[abbbcccdee]-->[1a3b4c1d2e] 我在这里的主要问题是关于1长模式的情况,因为“向

这是我在这里的第一篇文章,所以我希望我能遵守规则。 几天前我参加了一次工作面试,我遇到了一个我能解决的问题(直到现在)。 想法是(在C上,但我想它不是isuue):给定一个长度为n的字符*,您应该使用O(1)内存comp(就地更改),并将相同字符的模式压缩为“num+char”,其中num是模式长度,char是模式的字符。您可以假设内存足够长,可以包含预期的结果。预期时间补偿为O(n)

示例-[abbbcccdee]-->[1a3b4c1d2e]

我在这里的主要问题是关于1长模式的情况,因为“向前推”所有字母以得到前面的1,增加了复杂性。否则,我的想法是使用一个指针来指示下一个压缩模式的位置,并且它只在指针位于数组的常规扫描之后时才起作用

谢谢

压缩“相同字母模式”

我在这里的主要问题是关于1长模式的情况,因为“向前推”所有字母以得到前面的1,增加了复杂性

记下第一道工序所需的长度,以保持O(n)并从末端展开


2次传球

压缩:
从开始计算字符重复数开始遍历字符串:
--如果遇到数字,则出错。
--将任何重复的2个或更多字符替换为十进制长度,即文本后跟字符。
--计数单个字符的大小写。
请注意压缩数据的长度

展开:
source=&s[length]-1

destination=&s[长度+单个]-1

从头到尾遍历数组从
读取,然后写入
目标

--通过对阵列开始的特殊检测:
----检测缺少前一位数字的字符,然后将其作为“1”+字符写入目标。
----否则,将“数字+字符”复制到目标。按相反顺序复制这些字符,以便使用“12z”,复制“z”,“2”,然后是“1”

保险算法处理
案例

近似

压缩“相同字母模式”

我在这里的主要问题是关于1长模式的情况,因为“向前推”所有字母以得到前面的1,增加了复杂性

记下第一道工序所需的长度,以保持O(n)并从末端展开


2次传球

压缩:
从开始计算字符重复数开始遍历字符串:
--如果遇到数字,则出错。
--将任何重复的2个或更多字符替换为十进制长度,即文本后跟字符。
--计数单个字符的大小写。
请注意压缩数据的长度

展开:
source=&s[length]-1

destination=&s[长度+单个]-1

从头到尾遍历数组从
读取,然后写入
目标

--通过对阵列开始的特殊检测:
----检测缺少前一位数字的字符,然后将其作为“1”+字符写入目标。
----否则,将“数字+字符”复制到目标。按相反顺序复制这些字符,以便使用“12z”,复制“z”,“2”,然后是“1”

保险算法处理
案例


类似于

让我们把@chux惊人的答案变成真实的代码!以下代码:

#include <stdio.h>
#include <assert.h>
#include <ctype.h>
char *compress_num_to_str(char *out, size_t v) {
    // the standard output&reverse
    char *tmp = out;
    while (v) {
        *tmp++ = v % 10 + '0';
        v /= 10;
    }
    char *ret = tmp;
    while (tmp > out) {
        --tmp;
        char a = *tmp;
        *tmp = *out;
        *out = a;
        out++;
    }
    return ret;
}
char *compress(char *string) {
    if (*string == '\0') {
        return string;
    }

    // compress
    char *in = string;
    char *out = string;
    size_t single = 0;
    for (char c; (c = *in++) != '\0'; ) {
        // the letter is going to be written anyway
        char *const pos = in;
        // iterate over repeated letters
        while (c == *in) {
            ++in;
        }
        // if there are any repeated letters
        if (pos != in) {
            // output the count
            const size_t count = in - pos + 1;
            out = compress_num_to_str(out, count);
        } else {
            // a single char
            single++;
        }
        *out++ = c;
    }
    const size_t length = out - string;

    // expand
    in = &string[length];
    out = &string[length + single];
    *out = '\0';
    // I am not particularly happy at how this loops
    // it's unreadable, but hey - it's fast and it works.
    char c = *--in; // current character is buffered to be read
    int cont; // should _the next_ loop continue
    do {
        // this should be a letter always
        assert(!isdigit(c));
        *--out = c;
        // put the letter into destination
        if ((cont = in != string) && (c = *--in, isdigit(c))) {
            // copy up until digits
            do {
                *--out = c;
            } while ((cont = in != string) && (c = *--in, isdigit(c)));
        } else {
            // the next input is not a digit
            // add a one and repeat
            *--out = '1';
        }
    } while (cont);
    assert(in == string);
    assert(out == string);

    return string;
}
#define TEST(str)  printf("%s -> %s\n", str, compress((char[sizeof(str) * 2 - 1]){str}))
int main() {
    TEST("abbcccddddeef");
    TEST("aabcdee");
    TEST("");
    TEST("a");
    TEST("abcde");
    TEST("aaaaaaaaaaaaaaaaaab");
    TEST("aaaaaaaaaaaaaaaaaabbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb");
    TEST("abbbbbbbbbbbbbbbbbbbbbbbbbbbbbb");
}
    

让我们把@chux惊人的答案变成真实的代码!以下代码:

#include <stdio.h>
#include <assert.h>
#include <ctype.h>
char *compress_num_to_str(char *out, size_t v) {
    // the standard output&reverse
    char *tmp = out;
    while (v) {
        *tmp++ = v % 10 + '0';
        v /= 10;
    }
    char *ret = tmp;
    while (tmp > out) {
        --tmp;
        char a = *tmp;
        *tmp = *out;
        *out = a;
        out++;
    }
    return ret;
}
char *compress(char *string) {
    if (*string == '\0') {
        return string;
    }

    // compress
    char *in = string;
    char *out = string;
    size_t single = 0;
    for (char c; (c = *in++) != '\0'; ) {
        // the letter is going to be written anyway
        char *const pos = in;
        // iterate over repeated letters
        while (c == *in) {
            ++in;
        }
        // if there are any repeated letters
        if (pos != in) {
            // output the count
            const size_t count = in - pos + 1;
            out = compress_num_to_str(out, count);
        } else {
            // a single char
            single++;
        }
        *out++ = c;
    }
    const size_t length = out - string;

    // expand
    in = &string[length];
    out = &string[length + single];
    *out = '\0';
    // I am not particularly happy at how this loops
    // it's unreadable, but hey - it's fast and it works.
    char c = *--in; // current character is buffered to be read
    int cont; // should _the next_ loop continue
    do {
        // this should be a letter always
        assert(!isdigit(c));
        *--out = c;
        // put the letter into destination
        if ((cont = in != string) && (c = *--in, isdigit(c))) {
            // copy up until digits
            do {
                *--out = c;
            } while ((cont = in != string) && (c = *--in, isdigit(c)));
        } else {
            // the next input is not a digit
            // add a one and repeat
            *--out = '1';
        }
    } while (cont);
    assert(in == string);
    assert(out == string);

    return string;
}
#define TEST(str)  printf("%s -> %s\n", str, compress((char[sizeof(str) * 2 - 1]){str}))
int main() {
    TEST("abbcccddddeef");
    TEST("aabcdee");
    TEST("");
    TEST("a");
    TEST("abcde");
    TEST("aaaaaaaaaaaaaaaaaab");
    TEST("aaaaaaaaaaaaaaaaaabbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb");
    TEST("abbbbbbbbbbbbbbbbbbbbbbbbbbbbbb");
}
    

两个指针。一个用于阅读,一个用于写作。谢谢你的回复,我会澄清,我的问题是写指针在读指针之前的情况,这样它会超过我还没有扫描过的字符。顺便说一句,你描述一下。如果我们加上字母不包括数字的限制,这可以通过三个过程完成:首先压缩非1个字母的运行,扫描以找到最终长度,从末尾开始扩展1个字母的运行。有时,
char buffer[256]是不明显的
实际上是O(1),与O(256)相同。拥有一个足以提前数步的缓冲区似乎是一个很大的帮助。更好的是,
int频率[256]
也是O(1),它允许我们以O(n)为单位预计算输出缓冲区大小,然后与O(n)相加以计算输出字符串,并给出另一个O(n)…两个指针。一个用于阅读,一个用于写作。谢谢你的回复,我会澄清,我的问题是写指针在读指针之前的情况,这样它会超过我还没有扫描过的字符。顺便说一句,你描述一下。如果我们加上字母不包括数字的限制,这可以通过三个过程完成:首先压缩非1个字母的运行,扫描以找到最终长度,从末尾开始扩展1个字母的运行。有时,
char buffer[256]是不明显的
实际上是O(1),与O(256)相同。拥有一个足以提前数步的缓冲区似乎是一个很大的帮助。更好的是,
int频率[256]
也是O(1),它允许我们以O(n)为单位预计算输出缓冲区大小,然后与O(n)相加以计算输出字符串,并给出另一个O(n)。。。