题目描述:
大致思路:
-
第一步将数字 1 转化为字符串 1.
-
将上一步生成的字符串转化为数组形式, 并且对其进行相邻相同的元素进行排序:
function groupBy(arr: string[]) {
const initVal: string[][] = [];
const map = new Map<string, number>();
return arr.reduce((acc, cur, index) => {
if (map.has(cur) && acc.length - 1 === map.get(cur)!) {
acc[map.get(cur)!].push(cur);
} else {
map.set(cur, acc.length);
acc.push([cur]);
}
console.log(map);
return acc;
}, initVal);
}
it('groupBy', () => {
//相邻的才分组
expect(groupBy(['1', '2', '2', '1', '3'])).toEqual([['1'], ['2', '2'], ['1'], ['3']]);
expect(groupBy(['1', '1', '1', '2', '2', '1']))
.toEqual([['1', '1', '1'], ['2', '2'], ['1']]);
});
- 遍历数组, 获取当前元素第一个值和长度, 拼接为目标值.
export function transformArr(arr: string[][]) {
const transform = (len: number, val: string) => String(len) + val;
let res = '';
arr.forEach((item) => {
const len = item.length;
const val = item[0];
res += transform(len, val);
});
return res;
}
it('transformArr', () => {
expect(transformArr([['1']])).toEqual('11');
expect(transformArr([['1', '1']])).toEqual('21');
expect(transformArr([['2'], ['1']])).toEqual('1211');
expect(transformArr([['1', '1'], ['2']])).toEqual('2112');
});
4.最终代码:
export function countAndSay(n: number) {
if (n < 1 || n > 30) return '';
if (n === 1) return '1';
let str = '';
while (--n) {
const arr = groupBy(Array.from(str || '1'));
str = transformArr(arr);
}
return str;
}