每日一道算法Day23

156 阅读1分钟

题目描述:

image.png

大致思路:

  1. 第一步将数字 1 转化为字符串 1.

  2. 将上一步生成的字符串转化为数组形式, 并且对其进行相邻相同的元素进行排序:

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']]);
  });
  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;
}