[Algorithm][回溯][找出所有子集的异或总和再求和][全排列 II][电话号码的字母组合][括号生成]详细讲解

news2024/11/25 0:49:40

目录

  • 1.找出所有子集的异或总和再求和
    • 1.题目链接
    • 2.算法原理详解
    • 3.代码实现
  • 2.全排列 II
    • 1.题目链接
    • 2.算法原理详解
    • 3.代码实现
  • 3.电话号码的字母组合
    • 1.题目链接
    • 2.算法原理详解
    • 3.代码实现
  • 4.括号生成
    • 1.题目链接
    • 2.算法原理详解
    • 3.代码实现


1.找出所有子集的异或总和再求和

1.题目链接

  • 找出所有子集的异或总和再求和

2.算法原理详解

  • 思路:每次都只选一个数,此后只能选它后面的数
    • 全局变量
      • int path
      • int sum
    • DFS()设计
      • 函数头void DFS(nums, pos)
        • pos:下一层递归选择数时的起始下标
      • 函数体
        • 循环枚举还能选哪些数
      • 递归出口:不需要特定函数出口
    • 回溯:亦或运算消消乐
      请添加图片描述

3.代码实现

class Solution 
{
    int sum = 0;
    int path = 0;
public:
    int subsetXORSum(vector<int>& nums) 
    {
        DFS(nums, 0);
        return sum;
    }
    
    void DFS(vector<int>& nums, int pos)
    {
        sum += path;
        
        for(int i = pos; i < nums.size(); i++)
        {
            path ^= nums[i];
            DFS(nums, i + 1);
            path ^= nums[i]; // 回溯,恢复现场
        }
    }
};

2.全排列 II

1.题目链接

  • 全排列 II

2.算法原理详解

  • 本题与全排列的区别就是本题主要考察剪枝
  • 剪枝情况
    • 同一个节点的所有分支中,相同的元素只能选择一次
      • nums[i] == nums[i - 1],则剪枝
    • 同一个数只能使用一次
      • 使用check数组剪枝
  • 剪枝思路:前提 -> 先把整个数组排序
    • 思路一:只关心”不合法”的分支
      • check[i] == true || (i != 0 && nums[i] == nums[i - 1] && check[i - 1] = false)
    • 思路二:只关心”合法”的分支
      • check[i] == false && (i == 0 || nums[i] != nums[i - 1] || check[i - 1] == true)
      • nums[i] != nums[i - 1]不成立隐含了一个条件nums[i] == nums[i - 1],此时才去看条件check[i - 1] == true
        请添加图片描述

3.代码实现

// 剪枝 v1.0
class Solution 
{
    vector<vector<int>> ret;
    vector<int> path;
    vector<bool> check;
public:
    vector<vector<int>> permuteUnique(vector<int>& nums) 
    {
        check.resize(nums.size(), false);
        sort(nums.begin(), nums.end());
        
        DFS(nums);
        return ret;
    }
    
    void DFS(vector<int>& nums)
    {
        if(path.size() == nums.size())
        {
            ret.push_back(path);
            return;
        }
        
        for(int i = 0; i < nums.size(); i++)
        {
            // 剪纸 - 何时不进?
            if(check[i] == true || \
              (i != 0 && nums[i]== nums[i - 1] && check[i - 1] == false))
            {
                continue;
            }
            
            // 进
            path.push_back(nums[i]);
            check[i] = true;
            
            DFS(nums);
            
            path.pop_back(); // 回溯,恢复现场
            check[i] = false;
            
        }
    }
};
--------------------------------------------------------------------------------
// 剪枝 v2.0
class Solution 
{
    vector<vector<int>> ret;
    vector<int> path;
    vector<bool> check;
public:
    vector<vector<int>> permuteUnique(vector<int>& nums) 
    {
        check.resize(nums.size(), false);
        sort(nums.begin(), nums.end());
        
        DFS(nums);
        return ret;
    }
    
    void DFS(vector<int>& nums)
    {
        if(path.size() == nums.size())
        {
            ret.push_back(path);
            return;
        }
        
        for(int i = 0; i < nums.size(); i++)
        {
            // 剪纸 - 何时进?
            if(check[i] == false && \
              (i == 0 || nums[i] != nums[i - 1] || check[i - 1] == true))
            {
                path.push_back(nums[i]);
                check[i] = true;
                
                DFS(nums);
                
                path.pop_back(); // 回溯,恢复现场
                check[i] = false;
            }
        }
    }
};

3.电话号码的字母组合

1.题目链接

  • 电话号码的字母组合

2.算法原理详解

  • 本题为组合问题,大思路几乎与排列问题一致
  • 函数设计思路
    • 全局变量
      • string path
      • vector<string> ret
      • string [10]
    • DFS()设计DFS(digits, pos)
    • 递归出口path.size() == digits.size()
  • 细节:数字与字符串的映射关系 -> 字符串数组
    请添加图片描述

3.代码实现

class Solution 
{
    vector<string> ret;
    string path;
    
    // 按键映射字母
    string str[10] = {"", "", "abc", "def", \
        "ghi", "jkl", "mno", "pqrs", "tuv", "wxyz"};
public:
    vector<string> letterCombinations(string digits) 
    {
        if(digits.size() == 0)
        {
            return ret;
        }
        
        DFS(digits, 0);
        return ret;
    }
    
    void DFS(string& digits, int pos)
    {
        if(path.size() == digits.size())
        {
            ret.push_back(path);
            return;
        }
        
        for(auto& ch : str[digits[pos] - '0'])
        {
            path += ch;
            DFS(digits, pos + 1);
            path.pop_back(); // 回溯,恢复现场
        }
    }
};

4.括号生成

1.题目链接

  • 括号生成

2.算法原理详解

  • 首先要搞清楚,什么是有效的括号组合?
    1. 左括号的数量 = 右括号的数量
    2. 从头开始的任意一个子串,左括号的数量 >= 右括号的数量
  • 函数设计思路
    • 全局变量
      • int left, right, total
      • string path
      • vector<string> path
    • DFS()设计void DFS()
    • 递归出口right == n
    • 回溯:左括号递归返回后
    • 剪枝
      • left >= n
      • right >= left
        请添加图片描述

3.代码实现

class Solution 
{
    int left;
    int right = 0;
    int total = 0;

    string path;
    vector<string> ret;
public:
    vector<string> generateParenthesis(int n) 
    {
        total = n;
        DFS();
        return ret;
    }

    void DFS()
    {
        if(right == total)
        {
            ret.push_back(path);
        }

        // 递归 + 剪枝
        if(left < total)
        {
            path += '(';
            left++;

            DFS();
            
            // 回溯,恢复现场
            path.pop_back();
            left--;
        }

        if(right < left)
        {
            path += ')';
            right++;

            DFS();

            // 回溯,恢复现场
            path.pop_back(); 
            right--;
        }
    }
};

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1672782.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

PCIE协议-2-事务层规范-TLP Prefix Rules

2.2.10 TLP前缀规则 以下规则适用于任何包含TLP前缀的TLP&#xff1a; 对于任何TLP&#xff0c;TLP中byte0的Fmt[2:0]字段中的值100b表示存在TLP前缀&#xff0c;并且Type[4]位指示TLP前缀的类型。 Type[4]位中的值0b表示存在本地TLP前缀。Type[4]位中的值1b表示存在端到端TL…

数据结构与算法-排序算法1-冒泡排序

本文先介绍排序算法&#xff0c;然后具体写冒泡排序。 目录 1.排序算法简介 2.常见的排序算法分类如下图&#xff1a; 3.冒泡排序&#xff1a; 1.介绍&#xff1a; 2.动态图解 3.举例 4.小结冒泡排序规则 5.冒泡排序代码 6.优化 7.优化后时间 代码&#xff1a; 运…

Java | Leetcode Java题解之第88题合并两个有序数组

题目&#xff1a; 题解&#xff1a; class Solution {public void merge(int[] nums1, int m, int[] nums2, int n) {int p1 m - 1, p2 n - 1;int tail m n - 1;int cur;while (p1 > 0 || p2 > 0) {if (p1 -1) {cur nums2[p2--];} else if (p2 -1) {cur nums1[p…

Vue的学习 —— <vue指令>

目录 前言 正文 内容渲染指令 内容渲染指令的使用方法 v-text v-html 属性绑定指令 双向数据绑定指令 事件绑定指令 条件渲染指令 循环列表渲染指令 侦听器 前言 在完成Vue开发环境的搭建后&#xff0c;若想将Vue应用于实际项目&#xff0c;首要任务是学习Vue的基…

黑马基于Web-socket的java聊天室基本解析

要是用Web-socket协议&#xff0c;我们要前端upgrade升级成web-socket协议 首先我们要引入springboot的websocket起步依赖&#xff0c;这样子方便使用&#xff0c;自己指定版本注意 <dependency><groupId>org.springframework.boot</groupId><artifactId&…

绘唐3启动器怎么启动一键追爆款3正式版

绘唐3启动器怎么启动一键追爆款3正式版 工具入口 一.文案助手&#xff1a; 【注意&#xff01;&#xff01;】如果图片无显示&#xff0c;一般情况下被杀毒拦截&#xff0c;需关闭杀毒软件或者信任文件路径。 win10设置排除文件&#xff1a; 1.【新建工程】使用前先新建工程…

std::ref和std::cref的使用和原理分析

目录 1.用法 2.std::reference_wrapper介绍 3.std::ref原理分析 4.std::cref原理分析 5.总结 1.用法 它的定义如下&#xff1a; std::ref&#xff1a;用于包装按引用传递的值。 std::cref&#xff1a;用户包装按const引用传递的值。 C本身就有引用&#xff08;&&#…

使用 Python 中的 TensorFlow 检测垃圾短信

前言 系列专栏&#xff1a;机器学习&#xff1a;高级应用与实践【项目实战100】【2024】✨︎ 在本专栏中不仅包含一些适合初学者的最新机器学习项目&#xff0c;每个项目都处理一组不同的问题&#xff0c;包括监督和无监督学习、分类、回归和聚类&#xff0c;而且涉及创建深度学…

【鸿蒙开发】第二十四章 IPC与RPC进程间通讯服务

1 IPC与RPC通信概述 IPC&#xff08;Inter-Process Communication&#xff09;与RPC&#xff08;Remote Procedure Call&#xff09;用于实现跨进程通信&#xff0c;不同的是前者使用Binder驱动&#xff0c;用于设备内的跨进程通信&#xff0c;后者使用软总线驱动&#xff0c;…

一个基于servlet的MVC项目-登录验证

一、MVC的概念 MVC是Model、View、Controller的缩写&#xff0c;分别代表 Web 应用程序中的3种职责1 模型:用于存储数据以及处理用户请求的业务逻辑。 2视图:向控制器提交数据&#xff0c;显示模型中的数据。 3控制器:根据视图提出的请求&#xff0c;判断将请求和数据交给哪个…

Linux下网络命令

目录 需求1-查看本机是否存在22端口解法1解法2解法3 需求2-查看其他主机是否存在22端口解法1解法2解法3 需求3-查看TCP连接解法1/2 需求4-统计80端口tcp连接次数解法 需求5-查看总体网络速度解法 需求6-查看进程流量解法 需求7-dns解法 需求8-traceroute到baidu解法 需求9-查看…

git仓库使用

git仓库是会限制空间大小限制的 git网络库的容量限制_github仓库大小限制-CSDN博客 git是用于管理github的工具 电脑左下角搜索git打开GitBash.exe 进入到要下载到本地的目录 下载到本地的文件不要更改&#xff01; 如果要使用请务必把文件复制到别的空间去再在这个别的空间…

centos7中查询Nacos的安装路径和配置信息如何查找?

在 CentOS 7 上查询 Nacos 的安装路径和配置信息通常涉及几个步骤。这些步骤主要依赖于你是如何安装 Nacos 的&#xff08;比如使用压缩包还是 Docker 等方式&#xff09;。下面是一些通用的方法来帮助你找到 Nacos 的安装路径和配置信息&#xff1a; 1. 查找 Nacos 的安装路径…

智能自助终端主板RK3288/RK3568在酒店前台自助机方案的应用,支持鸿蒙,支持免费定制

酒店前台自助机解决方案是一款基于自助服务终端&#xff0c;能够让客人通过简单的操作完成入住登记/退房的解决方案&#xff0c;大幅提高酒店的工作效率&#xff0c;提升客人体验&#xff0c;降低人力成本。 该方案解决了以下传统前台登记入住方式的痛点&#xff1a; 1、人流量…

elasticsearch 动态映射

文章目录 动态映射动态映射的弊端静态映射实战&#xff1a;映射创建后还可以更新吗 动态映射 动态映射的核心是在自动检测字段类型后添加新字段 哪些字段类型支持动态检测呢&#xff1f; 答&#xff1a;boolean类型、float类型、long类型、Object类型、Array类型、date类型、…

Hive-表设计优化

Hive-表设计优化 1.Hive查询基本原理 Hive的设计思想是通过元数据解析描述将HDFS上的文件映射成表。 基本的查询原理是当用户通过HQL语句对Hive中的表进行复杂数据处理和计算时&#xff0c;默认将其转换为分布式计算MapReduce程序对HDFS中的数据进行读取处理的过程。 当执行…

黑马甄选离线数仓项目day02(数据采集)

datax介绍 官网&#xff1a; https://github.com/alibaba/DataX/blob/master/introduction.md DataX 是阿里云 DataWorks数据集成 的开源版本&#xff0c;在阿里巴巴集团内被广泛使用的离线数据同步工具/平台。 DataX 实现了包括 MySQL、Oracle、OceanBase、SqlServer、Postgre…

48-Qt控件详解:Buttons Containers2

一 Group Box:组合框 #include "widget.h"#include<QGroupBox> #include<QRadioButton> #include<QPushButton> #include<QVBoxLayout>//可以在水平方向和垂直方向进行排列的控件&#xff0c;QHBoxLayout/QVBoxLayout #include <QGridLa…

Adobe Media Encoder ME v24.3.0 解锁版 (视频和音频编码渲染工具)

Adobe系列软件安装目录 一、Adobe Photoshop PS 25.6.0 解锁版 (最流行的图像设计软件) 二、Adobe Media Encoder ME v24.3.0 解锁版 (视频和音频编码渲染工具) 三、Adobe Premiere Pro v24.3.0 解锁版 (领先的视频编辑软件) 四、Adobe After Effects AE v24.3.0 解锁版 (视…

新增柱线组合图、象限图,新增钉钉、飞书、企业微信客户端免密登录,DataEase开源数据可视化分析工具v2.6.0发布

2024年5月13日&#xff0c;人人可用的开源数据可视化分析工具DataEase正式发布v2.6.0版本。 这一版本的功能升级包括&#xff1a;图表方面&#xff0c;新增了柱线组合图、象限图&#xff1b;仪表板方面&#xff0c;支持批量拖拽字段&#xff0c;外部参数新增支持配置过滤组件&…