实际开发过程中,会因为 lgn 倍的时间复杂度优化而牺牲代码可读性吗

2020-10-21 16:16:17 +08:00
 YadongZhang

1. 场景描述:

TLDR:Draft.js 富文本框架中,根据文本的 type 可以将每一行文本划分为

 'unstyled', 'header-one', 'header-two', ..., 'header-six', 'atomic', // 其他类型暂不考虑

其中,在处理 unstyled 文本时,

已知 inlineStyleRangesEntityRanges 都是 sorted.

根据对象的 offset 属性,对两个 sorted 的数组进行升序排序 ( Merge Sorted Arrays)

2. 样例

类型定义:

type InlineStyleRangesType = {
    offset: number,
    length: number,
    style: 'BOLD' | 'CODE' | 'ITALIC' | 'STRIKETHROUGH' | 'UNDERLINE',
}[]

type EntityRangesType = {
    offset: number,
    length: number,
    key: number,
}[]

type SortedArrayType = {
    offset: number,
    length: number,
    key?: number,
    style?: 'BOLD' | 'CODE' | 'ITALIC' | 'STRIKETHROUGH' | 'UNDERLINE',
}[]

输入:

const a: InlineStyleRangesType = [
    { offset: 1, length: 1, style: "BOLD" },
    { offset: 9, length: 2, style: "ITALIC" },
]

const b: EntityRangesType = [
    { offset: 4, length: 1, key: 0 },
    { offset: 12, length: 1, key: 1 },
]

输出:

[
    { offset: 1, length: 1, style: "BOLD" }, 
    { offset: 4, length: 1, key: 0 },
    { offset: 9, length: 2, style: "ITALIC" },
    { offset: 12, length: 1, key: 1 },
] 

3. 解法

本人解法

// version 1

function mergeSortedArrays(
    inlineStyleRanges: InlineStyleRangesType,
    entityRanges: EntityRangesType
): SortedArrayType {
    const ranges = []

    inlineStyleRanges.forEach((range) => ranges.push(range))
    entityRanges.forEach((range) => ranges.push(range))

    ranges.sort((a, b) => a.offset - b.offset)

    return ranges
}

Interview Cake 解法

// version 2

function mergeSortedArrays(
    inlineStyleRanges: InlineStyleRangesType,
    EntityRanges: EntityRangesType
): SortedArrayType {
    const ranges = (inlineStyleRanges as SortedArrayType).concat(EntityRanges)

    ranges.sort((a, b) => a.offset - b.offset)

    return ranges
}
// version 3

function mergeSortedArrays(
    inlineStyleRanges: InlineStyleRangesType,
    EntityRanges: EntityRangesType
): SortedArrayType {
    const ranges = []

    let currentIndexEntity = 0;
    let currentIndexInlineStyle = 0;
    let currentIndexMerged = 0;

    while (currentIndexMerged < (inlineStyleRanges.length + EntityRanges.length)) {

	const isInlineStyleRangesExhausted = currentIndexInlineStyle >= inlineStyleRanges.length;
	const isEntityRangesExhausted = currentIndexEntity >= EntityRanges.length;

	// Case: next comes from inlineStyleRanges
	// inlineStyleRanges must not be exhausted, and EITHER:
	// 1) EntityRanges IS exhausted, or
	// 2) The current element in inlineStyleRanges is less
	//    than the current element in EntityRanges
	if (!isInlineStyleRangesExhausted
		&& (isEntityRangesExhausted
		|| (inlineStyleRanges[currentIndexInlineStyle].offset < EntityRanges[currentIndexEntity].offset)
	)) {

		ranges[currentIndexMerged] = inlineStyleRanges[currentIndexInlineStyle];
		currentIndexInlineStyle++;

	// Case: next comes from EntityRanges
	} else {
		ranges[currentIndexMerged] = EntityRanges[currentIndexEntity];
		currentIndexEntity++;
	}

	currentIndexMerged++;
    }

    return ranges
}

4. 算法分析

version 1 version 2 version 3
是否利用了 sorted 特性
时间复杂度 * O(nlgn) O(nlgn) O(n)
空间复杂度 O(n) O(n) O(n)
代码可读性 ★★★★★ ★★★★

* version 2 其实要优于 version 1 (常数倍)

3331 次点击
所在节点    职场话题
25 条回复
bleepbloop
2020-10-22 09:57:57 +08:00
工作好几年了,从没遇到数据量大到需要刻意优化算法的地步,可能我太菜了吧
py2ex
2020-10-22 10:28:44 +08:00
以为 lgn 是什么新词,原来是 log N
YadongZhang
2020-10-22 11:17:19 +08:00
@py2ex #22

CLRS 3e, Chap.1, Sec.3.2, P57

By equation (3.15) 换底公式, changing the base of a logarithm from one constant to another changes the value of the logarithm by only a constant factor, and so we shall often use the notation “lg n” when we don’t care about constant factors, such as in O-notation.
shadeofgod
2020-10-22 12:55:07 +08:00
合并两个有序数组的也可以很容易写出兼顾可读性的写法吧?
shadeofgod
2020-10-22 12:55:52 +08:00

这是一个专为移动设备优化的页面(即为了让你能够在 Google 搜索结果里秒开这个页面),如果你希望参与 V2EX 社区的讨论,你可以继续到 V2EX 上打开本讨论主题的完整版本。

https://www.v2ex.com/t/717151

V2EX 是创意工作者们的社区,是一个分享自己正在做的有趣事物、交流想法,可以遇见新朋友甚至新机会的地方。

V2EX is a community of developers, designers and creative people.

© 2021 V2EX