已掉线,重新登录

首页 > 绿虎论坛 > 历史版块 > 编程 > PHP > 讨论/求助

一个算法题


『回复列表(24|隐藏机器人聊天)』

20.

@老虎会游咏q,19楼的方法似乎就是“动态规划”🤣🤣🤣

也就是做了前缀优化的排列组合。

采用逐层遍历+递归的方法生成排列,存储输入参数2元素个数的map通过值传递传给下一层,然后每层都进行取数尝试,一但某层取的数不存在,就从递归里返回false,放弃整个分支,回到下一个分支继续尝试。

因为存储输入参数2元素个数的map是值传递,所以层与层互不影响,return就能无损回溯。

(/@Ta/2021-11-04 00:19//)

21.

继续优化:存储输入参数2元素个数的map也可以引用传递,只需要在return false之前把自己的修改还原就行了。减少的值加回去,就回溯到以前的状态了。

如果是return true,那就不用还原了,因为答案已经找到了。

继续优化:
因为采用引用传递了,所以该算法也可以从递归改成迭代。只需要一个栈记录每层遍历到哪里了就行。递归其实就是在函数调用栈里记录了每层的遍历位置。

(/@Ta/2021-11-04 00:40//)

22.

看着老虎说的,按照自己的理解写了一段代码,但是这有个大问题:生成全排列的复杂度是O(n^n)。


// 描述: 手里有一组数字卡片,每个人说出自己想要的一组数字(只能领到一张想要的卡片)。要判断手里的卡片是否能按大家需要分配每一个人。
function main(desire, gift) {
  const combina = (arr1, arr2) => {
    let arr = [];
    for (let v1 of arr1) {
      for (let v2 of arr2) {
        arr.push(`${v1}${v2}`);
      }
    }
    return arr;
  };
  const generate = (arr, length) => {
    if (length <= 2) {
      return combina(arr[length - 2], arr[length - 1]);
    }
    return combina(generate(arr, length - 1), arr[length - 1]);
  };
  const fullArr = generate(desire, desire.length);
  return fullArr.some((item) => {
    const ngift = [...gift];
    const length = item.split("").length;
    for (let i = 0; i < length; i++) {
      const index = ngift.indexOf(Number(item[i]));
      if (index === -1) break;
      ngift.splice(index, 1);
      if (i === length - 1) {
        return true;
      }
    }
    return false;
  });
}
console.log(main([[1, 2], [1, 3], [3]], [1, 3, 4]));


红米K30 Pro(变焦版)

(/@Ta/2021-11-04 10:52//)

23.

老虎也可能说的是这个意思: 回溯加剪枝


// 描述: 手里有一组数字卡片,每个人说出自己想要的一组数字(只能领到一张想要的卡片)。要判断手里的卡片是否能按大家需要分配每一个人。
function main(desire, gift) {
  const path = [];
  let status = false;
  const dfs = (index) => {
    if (index > desire.length - 1) {
      console.log("递归完成:", path);
      const ngift = [...gift];
      for (let i = 0; i < path.length; i++) {
        const index = ngift.indexOf(path[i]);
        if (index === -1) return;
        ngift.splice(index, 1);
        if (i === path.length - 1) {
          status = true;
        }
      }
      return;
    }
    for (let item of desire[index]) {
      path.push(item);
      console.log("递归前:", path);
      index++;
      dfs(index);
      if (status) {
        return;
      }
      path.pop();
      index--;
      console.log("递归后:", path);
    }
  };
  dfs(0);
  return status;
}
console.log(main([[1, 2], [1, 3], [3]], [1, 3, 3]));

红米K30 Pro(变焦版)

(/@Ta/2021-11-04 12:48//)

24.

提前设置好map,就不需要每次使用indexOf去判断了。


// 描述: 手里有一组数字卡片,每个人说出自己想要的一组数字(只能领到一张想要的卡片)。要判断手里的卡片是否能按大家需要分配每一个人。
function main(desire, gift) {
  const path = [];
  let status = false;
  const map = {};
  for (let item of gift) {
    if (map[item]) {
      map[item] = map[item] + 1;
    } else {
      map[item] = 1;
    }
  }
  const dfs = (index) => {
    if (status) {
      return;
    }
    if (index > desire.length - 1) {
      console.log("递归完成:", path);
      const nmap = { ...map };
      for (let i = 0; i < path.length; i++) {
        if (nmap[path[i]] && nmap[path[i]] > 0) {
          nmap[path[i]] = nmap[path[i]] - 1;
        } else {
          return;
        }
      }
      status = true;
      return;
    }
    for (let item of desire[index]) {
      path.push(item);
      console.log("递归前:", path);
      index++;
      dfs(index);
      path.pop();
      index--;
      console.log("递归后:", path);
    }
  };
  dfs(0);
  return status;
}
console.log(main([[1, 2], [1, 3, 4], [3]], [1, 3, 3]));


红米K30 Pro(变焦版)

(/@Ta/2021-11-04 12:47//)

上一页 2/2页,共24楼

回复需要登录

9月21日 21:50 星期天

本站由hu60wap6驱动

备案号: 京ICP备18041936号-1