【问题标题】:What's the runtime of Python's strip()?Python 的 strip() 的运行时间是多少?
【发布时间】:2015-02-25 09:15:56
【问题描述】:

Python 的 strip() 的运行时间是什么?

因为对于单个字符,remove 是 O(n),所以对于一个字符串,strip 是 O(n^2) 吗?

【问题讨论】:

  • str 上没有 str.delete,它们是不可变的。你的意思是 str.remove 创建新字符串?
  • str.remove 是什么意思?它不存在……
  • ^oops 抱歉,是的,我的意思是 remove() 操作。更新

标签: python python-2.7 python-internals


【解决方案1】:

它也只是 O(N)。引用与去除空格的普通 strip 对应的代码 from the version 2.7.9

Py_LOCAL_INLINE(PyObject *)
do_strip(PyStringObject *self, int striptype)
{
    char *s = PyString_AS_STRING(self);
    Py_ssize_t len = PyString_GET_SIZE(self), i, j;

    i = 0;
    if (striptype != RIGHTSTRIP) {
        while (i < len && isspace(Py_CHARMASK(s[i]))) {
            i++;
        }
    }

    j = len;
    if (striptype != LEFTSTRIP) {
        do {
            j--;
        } while (j >= i && isspace(Py_CHARMASK(s[j])));
        j++;
    }

    if (i == 0 && j == len && PyString_CheckExact(self)) {
        Py_INCREF(self);
        return (PyObject*)self;
    }
    else
        return PyString_FromStringAndSize(s+i, j-i);
}

它首先从左边开始,递增变量i,直到找到一个非空格字符,然后从右边开始递减j,直到找到一个非空格字符。最后,ij 之间的字符串也随之返回

PyString_FromStringAndSize(s+i, j-i)

但另一方面,the strip which removes the set of characters 稍微复杂但非常相似。

Py_LOCAL_INLINE(PyObject *)
do_xstrip(PyStringObject *self, int striptype, PyObject *sepobj)
{
    char *s = PyString_AS_STRING(self);
    Py_ssize_t len = PyString_GET_SIZE(self);
    char *sep = PyString_AS_STRING(sepobj);
    Py_ssize_t seplen = PyString_GET_SIZE(sepobj);
    Py_ssize_t i, j;

    i = 0;
    if (striptype != RIGHTSTRIP) {
        while (i < len && memchr(sep, Py_CHARMASK(s[i]), seplen)) {
            i++;
        }
    }

    j = len;
    if (striptype != LEFTSTRIP) {
        do {
            j--;
        } while (j >= i && memchr(sep, Py_CHARMASK(s[j]), seplen));
        j++;
    }

    if (i == 0 && j == len && PyString_CheckExact(self)) {
        Py_INCREF(self);
        return (PyObject*)self;
    }
    else
        return PyString_FromStringAndSize(s+i, j-i);
}

和上一个一样,但是每次都有额外的memchr(sep, Py_CHARMASK(s[j]), seplen)检查。所以,它的时间复杂度变成了 O(N * M),其中M 是要被剥离的实际字符串的长度。

【讨论】:

  • @jamylak 太酷了。在步长为 1 的情况下,字符串切片也可能是 O(1),是吗?
  • @Ryan True 它只是增加引用并返回完全相同的字符串hg.python.org/cpython/file/648dcafa7e5f/Objects/…
  • @jamylak: PyString_FromStringAndSize() 返回一个副本。否则,谁拥有哪些部分的问题可能会使垃圾收集复杂化。它仅针对 s[0:len(s):1] 情况返回相同的字符串。
  • s.strip(sep)O(len(s) * len(sep))O(n*m),而不是O(n*n),其中m(实际上)受字母大小的限制(在这种情况下为256)。
  • @J.F.Sebastian 你是对的 :-) 更新了我的答案。
猜你喜欢
  • 1970-01-01
  • 2019-06-22
  • 1970-01-01
  • 2017-12-28
  • 1970-01-01
  • 2014-05-01
  • 1970-01-01
  • 1970-01-01
  • 2020-06-13
相关资源
最近更新 更多