起因
前段时间做了一个两数之和,突然想挑战一下三数之和,做的过程中发现一个问题,在类型体操中没有一个数组排序的方法,只能自己写一个了。
思路
首先用体操来解决排序相对于正常的排序算法有个非常明显的问题体操是无法进行大于小于操作,也无法进行数字运算,那我们应该如何解决比对问题呢。 先理清一下思路(这里我们只考虑整数),我们可以先将整个数组元素分成三种,0、负数、正数,我们分别对负数和正数进行排序,最后将他们拼接起来。这里我们要考虑另外一个问题如何比对,我有两个元素我如何解决判断那个元素大的问题,我们可以写一个工具函数max来解决,让max有一个默认参数然后递归去调用这个max方法,去做比对。下面我来详细的说一下具体的coding实现和详细的思路。
第一步处理成二维数组
这里同两数之和一样我们需要先转化成二维数组用做比对和便利,这里还有一个问题就是负数的问题,我们可以降假如这个数是正数比如2转化成[1,1]如果是-2转化成[-1,-1], OK下面来实现coding。(具体原因可以参考两数之和第一步)
type NumArrayToArray<T extends number[], arr extends unknown[][] = [], index extends unknown[] = [], item extends unknown[] = []> =
T['length'] extends arr['length'] ? arr : `${T[arr['length']]}` extends `-${infer i}` ? i extends `${item['length']}` ?
NumArrayToArray<T, [...arr, item], [...index, -1]> : NumArrayToArray<T, arr, index, [...item, -1]> : T[arr['length']] extends item['length'] ?
NumArrayToArray<T, [...arr, item], [...index, 1]> : NumArrayToArray<T, arr, index, [...item, 1]>
type test3 = NumArrayToArray<[-1, 0, 1, 2, -1, -4]> // [[-1], [], [1], [1, 1], [-1], [-1, -1, -1, -1]]
第二步max方法
我们先实现max方法方便后面的比对,这里我们应该如何实现max方法呢,我们需要先明确max方法的作用就是比对两个元组的length谁更长,确定需求之后就代表着我们的max方法需要传入两个泛型T、M,接下来我们可以下一个index用于记录长度,然后去递归max方法让index++,当index先等于T或者先等于M的时候说明另外一个数字一定是大于等于这个index的,直接上coding。
type MaxLengthArr<T extends unknown[], K extends unknown[], N extends unknown[] = []> =
N['length'] extends T['length'] ? K : N['length'] extends K['length'] ? T : MaxLengthArr<T, K, [...N, unknown]>
第三步实现插入
这一步我们需要实现一个功能,现在我有一个有序的元组如何插入一个新的元素还要让他保证是有序的,这里我们可以这么写,首先我有一个索引值index,我先去遍历这个元组当index索引的值大于这个值的时候,就说明他需要插入到index索引的前面,coding。
type InsertItem<Arr extends unknown[][], item extends unknown[], initArr extends unknown[][] = Arr, minArr extends unknown[][] = []> =
Arr extends [infer R extends unknown[], ...infer M extends unknown[][]] ? MaxLengthArr<R, item> extends R ?
[...minArr, item, R, ...M] : InsertItem<M, item, initArr, [...minArr, R]> : [...initArr, item]
type test2 = InsertItem<[[1], [1, 1, 1]], [1, 1, 1, 1]> // [[1], [1, 1, 1], [1, 1, 1, 1]]
第四步分整数类型的去比对实现插入
到这里其实我们只需要先对整个数组中所有的元素进行分组分成负数、正数、0,然后用上面的方法分别对他们进行排序并拼接起来返回,coding。
type SortArray<T extends unknown[][], Arr1 extends unknown[][] = [], Arr2 extends unknown[][] = [], Arr3 extends unknown[][] = [], item extends unknown[] = []> =
T extends [infer R extends unknown[], ...infer M extends unknown[][]] ? item['length'] extends 0 ? SortArray<M, Arr1, Arr2, [...Arr3, []], R> : item[0] extends -1 ?
SortArray<M, Arr1, InsertItem<Arr2, item>, Arr3, R> : item[0] extends 1 ? SortArray<M, InsertItem<Arr1, item>, Arr2, Arr3, R> : null : item[0] extends -1 ?
[item, ...Arr2, ...Arr3, ...Arr1] : item[0] extends 1 ? [...Arr2, ...Arr3, ...Arr1, item] : [...Arr2, ...Arr3, item, ...Arr1]
type Test = SortArray<NumArrayToArray<[-1, 0, 1, 2, -1, -4]>> // [[-1, -1, -1, -1], [-1], [-1], [], [], [1], [1, 1]]
总结
写完排序之后,发现了当我们失去了比对,数字运算等基础逻辑之后想实现排序很难有一个较好的时间复杂度来实现。下机下机~