从零学算法(LCR 157)

news/2024/7/20 20:29:34 标签: 算法, 深度优先

某店铺将用于组成套餐的商品记作字符串 goods,其中 goods[i] 表示对应商品。请返回该套餐内所含商品的 全部排列方式 。
返回结果 无顺序要求,但不能含有重复的元素。
示例 1:
输入:goods = “agew”
输出:[“aegw”,“aewg”,“agew”,“agwe”,“aweg”,“awge”,“eagw”,“eawg”,“egaw”,“egwa”,“ewag”,“ewga”,“gaew”,“gawe”,“geaw”,“gewa”,“gwae”,“gwea”,“waeg”,“wage”,“weag”,“wega”,“wgae”,“wgea”]

  • 我的原始人解法,遍历+回溯,其实就相当于有几个字母就进行几重循环,用 set 记录每种结果来去重,用另一个 set 来排除已使用字母并在使用后回溯
  •   char[] data;
      // 结果 set
      Set<String> ans = new HashSet<>();
      // 回溯 set
      Set<Integer> set = new HashSet<>();
      public String[] goodsOrder(String goods) {
          data = goods.toCharArray();
          dfs("",0);
          String[] res = new String[ans.size()];
          res = ans.toArray(res);
          return res;
      }
      // cur:当前组合的字符串,从空字符串开始拼接
      public void dfs(String cur){
      	// 根据字符串长度判断是否已经组成一个可能
      	// 是就记录到结果 set
          if(cur.length()==data.length){
              ans.add(cur);
              return;
          }
          for(int i=0;i<data.length;i++){
          	// 递归到下一层时依旧从 0~data.length 遍历,但是不能使用上一层已使用过的字符
              if(set.contains(i))continue;
              // 排除已使用的
              set.add(i);
              dfs(cur+data[i]);
              // 复原,保证每个字符都有机会成为头部字符,即无遗漏
              set.remove(i);
          }
      }
    
  • 他人题解:为了方案不遗漏,我们还可以通过固定第一位字符,再考虑剩下的字符的所有排列情况;再固定下一位,考虑剩下的所有情况…而所有情况的排列,我们通过原地交换字符来实现(这个算法的核心有一点,固定某位字符也可以看做交换,比如第 0 位和第 0 位交换,所以本质上我们就是通过从字符第 0 位到末尾第 n 位都尝试交换(0与0,0与1,0与2,0与3…),递归后尝试第 1 位到第 n 位的所有交换(1与1,1与2,1与3…),再递归尝试第 2 位到第 n 位交换的所有可能,以此保证每种可能性都不遗漏),例如 abc,我们先固定 a(交换 0,0),再固定 b(交换 1,1),最后剩下一位自然是直接可以返回一种结果了即 abc,回溯到 b 时,我们这次选择交换 1,2,得到 acb,再回溯到 a 时,我们上次是交换 0,0,这次我们选择交换 0,1,即交换 ab(此时为 [b,a,c]),然后第二位的 a 也是从 1,1 开始交换,再递归直接返回结果 bac,再回溯到 a,我们选择交换 1,2 了,最终得到 bca,然后又回溯到了最开始的 a,这次要选择交换 0,2 得到 [c,b,a]…,为了排除重复方案,我们在固定某个字符时,只需要保证它在某一位固定一次就够了,比如 aab,你在最外层遍历到第二个 a,其实就不需要再固定第二个 a 去递归了,因为得到的结果一定是重复的(固定 aa 其实就包含在固定 a 的结果中不是吗),因此我们同样需要一个 set 来记录,即剪枝操作,防止重复记录
  •   char[] data;
      List<String> res = new LinkedList<>();
      public String[] goodsOrder(String goods) {
          data = goods.toCharArray();
          dfs(0);
          return res.toArray(new String[res.size()]);
      }
      public void dfs(int x){
      	// 只剩一个字符了还组合什么,直接返回
          if(x==data.length-1){
              res.add(String.valueOf(data));
              return;
          }
          Set<Character> set = new HashSet<>();
          for(int i=x;i<data.length;i++){
              if(set.contains(data[i]))continue;
              set.add(data[i]);
              // 交换,以保证每种可能性不遗漏
              swap(i,x);
              // 开启下层递归,即固定了第 0~x 位字符,要去固定第 x+1 位了
              dfs(x+1);
              // 复原交换,等别人用来进行其他的交换方式
              swap(i,x);
          }
      }
      void swap(int a, int b) {
          char tmp = data[a];
          data[a] = data[b];
          data[b] = tmp;
      }
    

http://www.niftyadmin.cn/n/5116069.html

相关文章

【matplotlib】matplotlib的颜色表

【matplotlib】matplotlib的颜色表 文章目录 【matplotlib】matplotlib的颜色表1. 颜色表Reference 1. 颜色表 在使用matplotlib库进行绘图的时候&#xff0c;只需要指定关键字coloryour_color就能修改绘制的颜色了&#xff0c;具体的颜色表如下。 Reference https://finthon…

【单元测试】--高级主题

一、模拟与存根深入 在单元测试中&#xff0c;模拟&#xff08;Mock&#xff09;和存根&#xff08;Stub&#xff09;是两种常用的测试替代品&#xff0c;用于模拟外部依赖或模拟特定行为&#xff0c;以便测试能够独立运行。以下是深入了解模拟与存根的概念&#xff0c;以NUni…

解决 Vue3 + Element Plus 树形表格全选多选以及子节点勾选的问题

原文链接&#xff1a; 解决 Vue3 Element Plus 树形表格全选多选以及子节点勾选的问题 前言 最近用到了 Element Plus 组件库的中的树形表格&#xff0c;但官网例子只能做到一层勾选&#xff0c;不能做到多层勾选&#xff0c;无法满足业务需求&#xff0c;所以研究了下&#…

vscode代码快捷输入

Vscode代码片段快捷输入 常用的代码片段为了避免重复输入,可以使用Vsco的中用户代码片段进行设置,这样就可以实现快捷输入. 操作流程 如下 打开vscode的设置 2. 找到用户代码片段 3. 选择模板 4. 然后写入代码片段即可 上面的代码片段可以设置多个,看自己 重点关注的是 prefi…

剑指Offer || 057.存在重复元素 III

题目 给你一个整数数组 nums 和两个整数 k 和 t 。请你判断是否存在 两个不同下标 i 和 j&#xff0c;使得 abs(nums[i] - nums[j]) < t &#xff0c;同时又满足 abs(i - j) < k 。 如果存在则返回 true&#xff0c;不存在返回 false。 示例 1&#xff1a; 输入&…

Windows平台搭建wxWidgets 3.2.3开发环境

一.基础环境和使用的软件 操作系统:win11mingw工具集:i686-8.1.0-release-win32-sjljIDE:clionwxWidgets头文件:wxWidgets-3.2.3-headerswxWidgets库文件:wxMSW-3.2.3_gcc810_ReleaseDLL PS: 失败很多次才在网上看到, wxWidgets是挑mingw版本的.gcc用8.1,DLL就要用8.1 官网…

全链路压测专题---2、全链路压测架构和技术

如何开展全链路压测 业务模型梳理 首先应该将核心业务和非核心业务进行拆分&#xff0c;确认流量高峰针对的是哪些业务场景和模块&#xff0c;针对性的进行扩容准备梳理出对外的接口&#xff1a;使用MOCK&#xff08;模拟&#xff09;方式做挡板千万不要污染正常数据&#xf…

VPN访问外网的原理

一.前言 许多人都用VPN翻墙&#xff0c;那么VPN为什么可以做到访问外网&#xff1f; VPN的全称叫“Virtual Private Network”意思就是虚拟私人专用网络&#xff0c;是专用网络的延伸&#xff0c;通过VPN&#xff0c;可以模拟点对点专用连接的方式&#xff0c;通过共享和公共网…