学习记录:js算法(八十八):分割回文串

文章目录

    • 分割回文串
      • 思路一:回溯法
      • 思路二:动态规划
      • 方法三:记忆化搜索
      • 方法四:迭代法
      • 方法五:位运算

分割回文串

给你一个字符串 s,请你将 s 分割成一些子串,使每个子串都是 回文串。返回 s 所有可能的分割方案。

示例 1:
输入:s = "aab"
输出:[["a","a","b"],["aa","b"]]

示例 2:
输入:s = "a"
输出:[["a"]]

思路一:回溯法

function isPalindrome(str) {
    let left = 0, right = str.length - 1;
    while (left < right) {
        if (str[left] !== str[right]) {
            return false;
        }
        left++;
        right--;
    }
    return true;
}

function partition(s, start = 0, path = [], result = null) {
    if (result === null) {
        result = [];
    }
    
    if (start === s.length) {
        result.push([...path]);
        return result;
    }
    
    for (let i = start; i < s.length; i++) {
        if (isPalindrome(s.slice(start, i + 1))) {
            path.push(s.slice(start, i + 1));
            partition(s, i + 1, path, result);
            path.pop(); // 回溯
        }
    }
    return result;
}

function partitionPalindromes(s) {
    return partition(s);
}

讲解
使用回溯结合简单的回文检测来解决

  1. 定义辅助函数 isPalindrome:
    ○ 这个函数用于判断一个字符串是否为回文串。
    ○ 使用两个指针分别从字符串的头部和尾部向中心移动并比较字符是否相等。
  2. 定义递归函数 partition:
    ○ 参数包括:
    ■ s: 原始输入字符串。
    ■ start: 当前处理的子串起始位置。
    ■ path: 用于存储当前递归路径上的回文子串。
    ■ result: 最终结果数组,用于收集所有满足条件的分割方案。
    ○ 终止条件:当 start 等于字符串长度时,将 path 加入到结果数组 result 中。
    ○ 递归逻辑:
    ■ 遍历从 start 到字符串末尾的所有位置 i。
    ■ 如果从 start 到 i 的子串是回文串,则将其加入到 path 中。
    ■ 对剩余的字符串(从 i+1 开始)继续执行相同的操作。
    ■ 在递归结束后,从 path 中移除刚刚添加的子串,进行回溯。
  3. 调用 partition 函数:
    ○ 在主函数 partitionPalindromes 中,直接调用 partition 函数,无需额外参数,因为默认值已经设置好。

思路二:动态规划

var partition = function (s) {
    const n = s.length;
    const dp = Array.from({ length: n }, () => Array(n).fill(false));
    const result = [];

    // 预处理回文
    for (let end = 0; end < n; end++) {
        for (let start = end; start >= 0; start--) {
            if (s[start] === s[end] && (end - start <= 2 || dp[start + 1][end - 1])) {
                dp[start][end] = true;
            }
        }
    }

    function backtrack(start, path) {
        if (start === n) {
            result.push([...path]);
            return;
        }

        for (let end = start; end < n; end++) {
            if (dp[start][end]) {
                path.push(s.slice(start, end + 1));
                backtrack(end + 1, path);
                path.pop();
            }
        }
    }

    backtrack(0, []);
    return result;
};

思路

  1. 使用动态规划预处理字符串中的所有回文子串,以便在生成分割方案时快速查找。
  2. 创建一个二维数组 dp,其中 dp[i][j] 表示从索引 i 到 j 的子串是否为回文。
  3. 先填充 dp 数组,然后使用回溯算法生成分割方案。

步骤

  1. 初始化一个二维数组 dp,并根据回文的定义填充它。
  2. 使用嵌套循环遍历字符串,标记所有的回文子串。
  3. 定义 backtrack 函数,使用 dp 数组来检查子串是否为回文。
  4. 当找到一个回文子串时,加入路径并继续递归,直到到达字符串末尾。

方法三:记忆化搜索

function isPalindrome(str) {
    return str === str.split('').reverse().join('');
}

function partition(s) {
    const result = [];
    const memo = {};

    function backtrack(start, path) {
        if (start === s.length) {
            result.push([...path]);
            return;
        }

        for (let end = start + 1; end <= s.length; end++) {
            const substring = s.slice(start, end);
            if (memo[substring] === undefined) {
                memo[substring] = isPalindrome(substring);
            }
            if (memo[substring]) {
                path.push(substring);
                backtrack(end, path);
                path.pop();
            }
        }
    }

    backtrack(0, []);
    return result;
}

思路:

  1. 结合回溯法和记忆化搜索,避免重复计算回文检查。
  2. 使用一个缓存对象 memo 来存储已经检查过的子串的回文结果。

步骤:

  1. 定义 isPalindrome 函数来检查回文。
  2. 在 partition 函数中,定义 backtrack 函数,尝试每个可能的子串。
  3. 在检查子串是否为回文时,首先查看 memo 是否已有结果,如果没有,则进行检查并存储结果。
  4. 继续回溯,直到找到所有可能的分割方案。

方法四:迭代法

function partition(s) {
    const result = [];
    const stack = [[0, []]];

    while (stack.length) {
        const [start, path] = stack.pop();

        if (start === s.length) {
            result.push(path);
            continue;
        }

        for (let end = start + 1; end <= s.length; end++) {
            const substring = s.slice(start, end);
            if (substring === substring.split('').reverse().join('')) {
                stack.push([end, [...path, substring]]);
            }
        }
    }

    return result;
}

思路:

  1. 使用迭代而非递归来生成所有可能的分割方案。
  2. 使用栈来存储当前的起始位置和分割路径。

步骤:

  1. 初始化一个栈,并将起始位置和空路径压入栈中。
  2. 当栈不为空时,弹出栈顶元素。
  3. 如果当前起始位置等于字符串长度,则将当前路径添加到结果中。
  4. 遍历从当前起始位置到字符串末尾的所有可能子串,检查它们是否为回文。
  5. 如果是回文,则将其加入路径并将新的状态压入栈中。

方法五:位运算

function isPalindrome(str) {
    return str === str.split('').reverse().join('');
}

function partition(s) {
    const n = s.length;
    const result = [];
    const totalCombinations = 1 << n; // 2^n

    for (let i = 0; i < totalCombinations; i++) {
        const path = [];
        let lastIndex = 0;

        for (let j = 0; j < n; j++) {
            if (i & (1 << j)) {
                const substring = s.slice(lastIndex, j + 1);
                if (isPalindrome(substring)) {
                    path.push(substring);
                    lastIndex = j + 1;
                }
            }
        }

        if (lastIndex === n) {
            result.push(path);
        }
    }

    return result;
}

思路:

  1. 利用位运算生成所有可能的分割方案。
  2. 通过位掩码的方式来表示每个字符是否为分割点。

步骤:

  1. 计算字符串的总组合数(2^n)。
  2. 遍历所有组合,使用位运算来确定哪些字符是分割点。
  3. 对于每个组合,检查生成的子串是否为回文。
  4. 如果最后的分割方案有效(即所有字符都被处理),将其添加到结果中。

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

前端中的 File 和 Blob两个对象到底有什么不同

JavaScript 在处理文件、二进制数据和数据转换时&#xff0c;提供了一系列的 API 和对象&#xff0c;比如 File、Blob、FileReader、ArrayBuffer、Base64、Object URL 和 DataURL。每个概念在不同场景中都有重要作用。下面的内容我们将会详细学习每个概念及其在实际应用中的用法…

一步一步从asp.net core mvc中访问asp.net core WebApi

"从asp.net core mvc中访问asp.net core WebApi"看到这个标题是不是觉得很绕口啊&#xff0c;但的确就是要讲一讲这样的访问。前面我们介绍了微信小程序访问asp.net core webapi(感兴趣的童鞋可以看看前面的博文有关WEBAPI的搭建)&#xff0c;这里我们重点不关心如何…

【Linux系列】VNC安装ssh后,ssh无法登录

&#x1f49d;&#x1f49d;&#x1f49d;欢迎来到我的博客&#xff0c;很高兴能够在这里和您见面&#xff01;希望您在这里可以感受到一份轻松愉快的氛围&#xff0c;不仅可以获得有趣的内容和知识&#xff0c;也可以畅所欲言、分享您的想法和见解。 推荐:kwan 的首页,持续学…

温度虽寒,其道犹变:OpenAI接口之温度参数设置为0,为何每次回复仍有不确定性?

问题描述 调用openai API&#xff0c;使用templature 0&#xff0c;每次返回的内容仍有一些不同 >>> client OpenAI( ... api_keyapi_key, ... base_urlapi_base) #第一次尝试 >>> response client.chat.completions.create(mo…

【软件测试】需求的概念和常见模型(瀑布、螺旋、增量、迭代)

1. 什么是需求 在企业中&#xff0c;经常会听到&#xff1a;用户需求和软件需求 用户需求&#xff1a;没用经过合理的评估&#xff0c;通常就是一句话&#xff08;开发一个五彩斑斓的黑&#xff09;软件需求&#xff1a;开发人员和测试人员执行工作的依据 1.2 软件需求 在工…

食品配送管理系统(源码+文档+部署+讲解)

食品配送管理系统是成品商业化项目&#xff0c;系统可基于源码二开。 系统概述 餐饮食品配送&#xff0c;包含配送人APP、下单APP、管理端等&#xff0c;实现订餐、配餐&#xff0c;用于食品店、中央厨房等订餐、团餐业务 本项目名称为食品配送系统&#xff0c;是针对食品配…

./bin/mindieservice_daemon启动成功

接MindIE大模型测试及报错Fatal Python error: PyThreadState_Get: the function must be called with the GIL held,-CSDN博客经过调整如下红色部分参数&#xff0c;昇腾310P3跑起来了7b模型&#xff1a; rootdev-8242526b-01f2-4a54-b89d-f6d9c57c692d-qjhpf:/home/apulis-de…

我谈维纳(Wiener)复原滤波器

Rafael Gonzalez的《数字图像处理》中&#xff0c;图像复原这章内容几乎全错。上篇谈了图像去噪&#xff0c;这篇谈图像复原。 图像复原也称为盲解卷积&#xff0c;不处理点扩散函数&#xff08;光学传递函数&#xff09;的都不是图像复原。几何校正不属于图像复原&#xff0c…

精选 Top10 开源调度工具,解锁高效工作负裁自动化

在大数据和现代 IT 环境中&#xff0c;任务调度与工作负载自动化&#xff08;WLA&#xff09;工具是优化资源利用、提升生产效率的核心驱动力。随着企业对数据分析、实时处理和多地域任务调度需求的增加&#xff0c;这些工具成为关键技术。 本文将介绍当前技术发展背景下的Top …

高效视觉方案:AR1335与i.MX8MP的完美结合

方案采用NXP i.MX8MP处理器和onsemi AR1335图像传感器&#xff0c;i.MX8MP集成四核Cortex-A53、NPU及双ISP技术。AR1335是一颗分辨率为13M的CMOS传感器。它使用了先进的BSI技术&#xff0c;提供了超高的分辨率和出色的低光性能&#xff0c;非常适合于需要高质量图像的应用。此外…

Ubuntu+ROS 机械臂拾取和放置

官方链接&#xff1a;https://github.com/skumra/baxter-pnp 1.下载并安装 SDK 依赖项 sudo apt-get install python-wstool python-rosdep 2.创建新的 catkin 工作区 mkdir -p ~/ros_ws/src cd ~/ros_ws/src 3.使用 wstool 下载 rosinstall 文件并将其复制到 Catkin 工作区…

论文阅读《Structure-from-Motion Revisited》

摘要 增量式地运动结构恢复是从无序图像集合中进行三维重建的一个普遍策略。虽然增量式地重建系统在各个方面上都取得了巨大的进步&#xff0c;但鲁棒性、准确性、完整度和尺度仍然是构建真正通用管道的关键问题。我们提出了一种新的运动结构恢复技术&#xff0c;它改进了目前…

基于Spring Boot的船运物流管理系统的设计与实现,LW+源码+讲解

摘要 近年来&#xff0c;信息化管理行业的不断兴起&#xff0c;使得人们的日常生活越来越离不开计算机和互联网技术。首先&#xff0c;根据收集到的用户需求分析&#xff0c;对设计系统有一个初步的认识与了解&#xff0c;确定船运物流管理系统的总体功能模块。然后&#xff0…

威联通Docker Compose搭建NAS媒体库资源工具NAS Tools

文章目录 一、环境配置1-1 需要的配件1-2 环境安装及配置注意:获取PUID/PGID1-3 目录位置准备总结,这里我们要做5件事备注:Docker无法下载解决办法二、登录配件,进行配件连接和配置2-1 jackett设置2-2 qBittorrent设置!!!设置文件下载地址2-3 jellyfin设置2-4 NASTools设…

Spring Boot - 扩展点 EnvironmentPostProcessor源码分析及真实案例

文章目录 概述EnvironmentPostProcessor 作用EnvironmentPostProcessor 实现和注册创建类并实现接口注册到 Spring Boot常见应用场景 源码分析1. EnvironmentPostProcessor 接口定义2. 扩展点加载流程3. 加载 EnvironmentPostProcessor 实现类4. EnvironmentPostProcessor 执行…

【eNSP】企业网络架构链路聚合、数据抓包、远程连接访问实验(二)

一、实验目的 网络分段与VLAN划分&#xff1a; 通过实验了解如何将一个大网络划分为多个小的子网&#xff08;VLAN&#xff09;&#xff0c;以提高网络性能和安全性。 VLAN间路由&#xff1a; 学习如何配置VLAN间的路由&#xff0c;使不同VLAN之间能够通信。 网络设备配置&am…

Python 智取京东商品详情:代码秘籍大公开

介绍使用 Python 获取京东商品详情的背景和意义&#xff0c;强调其在数据收集和分析中的重要性。 &#xff08;一&#xff09;数据收集的需求 在当今数字化的商业环境中&#xff0c;对京东商品详情数据的需求日益增长。市场调研人员需要这些数据来了解不同产品的市场份额、价格…

[C++]——位图与布隆过滤器

目录 一、前言 二、正文 1.位图 1.1 位图概念 1.2 位图的实现 1.2.1 Set 1.2.2 ReSet 1.2.3 Text 1.3 位图的应用 2.布隆过滤器 2.1布隆过滤器的提出 2.2 布隆过滤器概念 2.3 布隆过滤器的实现 2.3.1布隆过滤器的插入 2.3.2 布隆过滤器的查找 2.3.3 布隆过滤器…

工具收集 - java-decompiler / jd-gui

工具收集 - java-decompiler / jd-gui 参考资料 用法&#xff1a;拖进来就行了 参考资料 https://github.com/java-decompiler/jd-gui 脚本之家&#xff1a;java反编译工具jd-gui使用详解

Spark的容错机制:persist持久化机制checkpoint检查点机制区别

persist持久化机制&#xff1a; 作用&#xff1a;将RDD的数据缓存到内存或磁盘中&#xff0c;以便在后续操作中重复使用&#xff0c;减少计算开销。特点&#xff1a; 灵活性高&#xff1a;可以指定不同的存储级别&#xff08;如仅内存、内存和磁盘、仅磁盘等&#xff09;。 数…