[剑指Offer] 5 替换空格

2023-11-18

题目: 5 替换空格

描述

请实现一个函数, 把字符串中的每个空格替换成"%20".

  • 示例

    输入: "We are happy!"
    输出: "We%20are%20happy!"

  • 注意

    应该判断是否有空间限制
    此处限制为只能在原字符数组进行替换, 假设数组给定足够的空余内存

思路

因为是在原数组上进行操作, 主要需要考虑如何移动有效数据

  1. 从前往后移动, 每次遇到空格, 就将空格以后的字符向后移动2个位置
    数组向后移动两格

  2. 从后往前移动, 因为有足够的空余位置, 所以直接从结果(成功替换后)的最后位置出发
    逐个替换原有效字符, 遇到空格就相当于加速前进
    从后往前把字符替换

代码实现

class Solution {

    /********
     * 暴力破解
     * 从头到尾遍历 
     * 每次遇到空格先将数组从该位置向后移动两格
     * 并在此填充"%20"
     * 
     * 注意:
     *  假设没有足够的空间创建新的字符数组
     *  只能在原数组上替换, 原数组后面提供足够的空余
     * 
     * @param chs 需要进行转换的字符数组
     */
    public void bruteReplaceBlank(char[] chs) {
        if (null == chs) return;
        
        int len = chs.length;
        if (len == 0) return;

        for (int i = 0; i < len; i++) {
            if (chs[i] == '\0') {
                break;
            } else if (chs[i] == ' ') {
                pushBack(chs, i+1);
                chs[i] = '%'; chs[i+1] = '2'; chs[i+2] = '0';
            }
        }
    }

    /******
     * 将字符串数组从指定位置向后移动两格
     */
    void pushBack(char[] chs, int start) {
        char front1 = ' ';
        char front2 = ' ';
        for (int i = start; i < chs.length-1; i=i+2) {
            char t1 = chs[i];
            char t2 = chs[i+1];
            chs[i] = front1;
            chs[i+1] = front2;
            front1 = t1;
            front2 = t2;
        }
    }

    /************************************************
     * 方法二:从后往前处理字符
     */

     public void fromEndReplaceBlank(char[] chs) {
        if (null == chs) return;
        
        int len = chs.length;
        if (len == 0) return;

        // realLen 字符串有效长度
        int realLen = 0;
        // blankCount 字符串中空格数 需要替换的空格
        int blankCount = 0;
        int i = 0;
        while (chs[i] != '\0') {
            if (chs[i] == ' ') {
                blankCount++;
            }
            realLen++;
            i++;
        }

        // 只有一个空格字符的情况
        if (blankCount == realLen) {
            chs[0] = '%'; chs[1] = '2'; chs[2] = '0';
            return;
        }

        // p 表示替换空格后, 有效字符数组最后一位下标
        // q 表示当前有效字符数组最后一位下标
        int p = realLen + 2*blankCount, q = realLen;
        // 需要替换的字符过多 超出原字符数组的边界
        if (p > len) return;
        
        while (q >= 0 && p > q) {
            if (chs[q] != ' ') {
                chs[p--] = chs[q];
            } else {
                chs[p--] = '0';
                chs[p--] = '2';
                chs[p--] = '%';
            }
            q--;
        }
     }
}
  • 测试
public class ReplaceBlank {
    static Solution s = new Solution();

    public static void main(String[] args) {
        // 测试用例包含空格
        // 空格在前面    " we are happy!"
        unitTest(generateTestChars(" we are happy!"));
        // 空格在中间    "we are happy!"
        unitTest(generateTestChars("we are happy!"));
        // 空格在后面    "we are happy! "
        unitTest(generateTestChars("we are happy! "));
        
        // 测试用例没有包含空格
        // 没空格字符数组 "wearehappy!"
        unitTest(generateTestChars("wearehappy!"));
        
        // 特殊测试用例
        // 空指针        null
        s.bruteReplaceBlank(null);
        s.fromEndReplaceBlank(null);
        // 空字符串      ""
        unitTest(new char[]{});
        // 只有一个空格字符 " "
        unitTest(generateTestChars(" "));
        // 有连续多个空格   "we  are  happy!"
        unitTest(generateTestChars("we  are  happy!"));
    }

    static void unitTest(char[] chs) {
        char[] test = Arrays.copyOf(chs, chs.length);
        s.bruteReplaceBlank(test);
        System.out.println("By Brute: " + Arrays.toString(test));
        test = Arrays.copyOf(chs, chs.length);
        s.fromEndReplaceBlank(test);
        System.out.println("From Back: " + Arrays.toString(test));
        System.out.println("---------------------------------------------");
    }

    /***
     * 生成测试字符数组
     * 
     * @param str 被包含的字符串
     * @return 有足够空余空间且包含str内容的字符数组
     */
    static char[] generateTestChars(String str) {
        int len = str.length();
        char[] chs = Arrays.copyOf(str.toCharArray(), 3 * len);
        return chs;
    }
}

相关题目: 合并两个排序数组到其中一个数组中

描述

有两个排序的数组A1和A2, 内存在A1的末尾有足够多的空余空间容纳A2.
请实现一个函数, 把A2中的所以数字插入A1中, 并且所有数字是排序的.

  • 示例

    输入: A1 = [1, 3, 5, 7, , , , ,] A2 = [2, 4, 6, 8]
    输出: A1 = [1, 2, 3, 4, 5, 6, 7, 8]

思路

采用本例题的思想, 从尾到头比较A1和A2中的数字, 并把较大的数字复制到A1中的合适位置.

代码实现

class Solution {

    /*********
     * 合并两个排序数组到第一个数组内
     * 使用从后往前合并的方式
     * 
     * @param A1 被合并数组
     * @param A2 合并数组
     * @param len1 A1的有效数字长度
     * @param len2 A2的有效数字长度
     */
    public void mergeSortedArrays(int[] A1, int[] A2, int len1, int len2) {
        if (A1 == null || A2 == null) return;

        // 当A1为空数组时, 直接复制A2到A1
        if (len1 == 0) {
            A1 = Arrays.copyOf(A2, A2.length);
            return;
        }

        // 合并后数组最尾部的下标
        int endOfMergeIndex = len1+len2-1;
        // p表示A1尾部  q表示A2尾部
        int p = len1-1, q = len2-1;
        while (p >= 0 && q >= 0) {
            if (A1[p] > A2[q]) {
                A1[endOfMergeIndex--] = A1[p--];
            } else {
                A1[endOfMergeIndex--] = A2[q--];
            }
        }
        // 当A2没合并完
        while (q > 0) {
            A1[endOfMergeIndex--] = A2[q--];
        }
    }
}
  • 测试
public class MergeSortedArrays {
    static Solution s = new Solution();

    public static void main(String[] args) {
        // 测试用例 准备
        int[] A11 = {1,3,5,6};
        int[] A2 = {2,4,6,8};
        // 有足够的空间合并A2
        int[] A1 = Arrays.copyOf(A11, A11.length+A2.length);

        System.out.println("before: " + Arrays.toString(A1));
        // before: [1, 3, 5, 6, 0, 0, 0, 0]
        s.mergeSortedArrays(A1, A2, A11.length, A2.length);
        System.out.println("after: " + Arrays.toString(A1));
        // after: [1, 2, 3, 4, 5, 6, 6, 8]
    }
}

转载于:https://www.cnblogs.com/slowbirdoflsh/p/11296312.html

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

[剑指Offer] 5 替换空格 的相关文章

随机推荐

  • Ubuntu18.04安装CUDA11.3和cuDNN8.2.0

    今天在服务器上跑代码 发现报错 说是CUDA版本不对 然后看了一下服务器的版本 发现是9 0 这就有问题了啊 3090的显卡得用11 0上的版本啊 所以接着配置一下深度学的环境 记录一下方便以后查阅 Ubuntu18 04安装CUDA11
  • cocos2dx跨平台直播实例-ffmpeg-ios篇

    一 环境 mac 10 12 2 cocos2dx 3 13 1 ffmpeg 3 0 二 新建项目和编译库 cocos2dx按照官网新建一个实例 ffmpeg编译ios库http blog csdn net u013654125 arti
  • delphi取得文件图标并在TListView中显示

    delphi取得文件图标并在TListView中显示 技术要点 一 使用SHGetFileInfo函数获取指定扩展名的文件图标 需要引用ShellAPI单元 二 使用TStringList来保存扩展名与其图标的索引号 当添加一个文件名至TL
  • Linux 虚拟化网络技术 — 虚拟网络协议栈

    前言 本文通过 OpenStack Neutron L3 Agent 实现的 Linux 虚拟路由器来描述 Linux 的虚拟网络协议栈 Neutron L3 agent 概述 Neutron L3 agent 服务 运行在 OpenSta
  • ubutun18.04安装Ros-melodic

    在Mac下使用虚拟机VMware Fusion安装了Ubuntu18 04系统 并在Ubuntu系统安装Ros 按照版本要求18系统对应Ros melodic 鉴于在网上很少在Mac上装Ros melodic 以该文章以记录安装的过程 一
  • 数组的对数器

    原创是某客的左程云老师 我只是加了点自己的注释记个笔记 package basic class 01 import java util Arrays 对数器的作用 对数器可以验证算法是否正确 在比赛或者笔试的时候 如果需要大量的测试用例 而
  • 正则表达式的相关用法

    正则表达式 又称规则表达式 英语 Regular Expression 在代码中常简写为regex regexp或RE 计算机科学的一个概念 正则表通常被用来检索 替换那些符合某个模式 规则 的文本 大家在写正则表达式的过程中 可利用开源中
  • postgresql 数据库的备份与恢复(命令模式)

    Postgresql备份和恢复 SQL转储篇 Postgresql备份和恢复 SQL转储篇 作者 小P来自 LinuxSir Org摘要 和任何包含珍贵数据的东西一样 PostgreSQL 数据库也应该经常备份 备份PostgreSQL数据
  • git的命令操作,gitee的使用,详细图片教程

    目录 Git的区域概念图 Git的 Git Bash Here 命令操作 Gitee操作 SSH公钥注册流程 创建和操作版本库 Git的区域概念图 Git的 Git Bash Here 命令操作 1 创建一个普通文件夹 进入文件夹后 右键选
  • MultipartFile报No such file or directory

    原因 当使用MultipartFile做上传操作时 1 spring是先将上传文件存放在一个临时地址 默认 tmp目录下 2 进入controller进行业务操作 linux环境中 tmp目录是存放临时文件的 当这个目录下的子目录10天之内
  • canvas.drawBitmap(bitmap, src, dst, paint)

    GameView drawImage canvas mBitDestTop miDTX mBitQQ getHeight mBitDestTop getWidth mBitDestTop getHeight 2 0 0 public sta
  • DBeaver连接阿里云mysql步骤

    DBeaver连接阿里云mysql步骤 dbeaver是免费和开源 GPL 为开发人员和数据库管理员通用数据库工具 重点是免费并且很好用 本人因为navicat收费而经网友推荐发现这个软件 这个真是个宝藏软件 由于这个过程也是我慢慢摸索的
  • java项目与web项目中lib包

    lib包 一 java项目 1 过程 2 注意 二 web项目 1 过程 2 不自动加载问题解决方法 一 java项目 1 过程 1 在java项目下建一个lib的Folder 2 复制相关jar包到lib中 3 全选 点第一个jar包 按
  • 双层for循环时间复杂度_时间复杂度的表示、分析、计算方法……一文带你看懂时间复杂度

    作者 OverRedMaple 责编 Carol 来源 CSDN 博客 封图 CSDN付费下载于东方 IC 如果你还在发愁究竟怎么计算时间复杂度和空间复杂度 那你是来对地方了 名词解释 在计算机科学中 时间复杂性 又称时间复杂度 算法的时间
  • 路面监控服务器怎么维修,路面监控服务器怎么维修

    路面监控服务器怎么维修 内容精选 换一换 用户云服务器基本网络功能异常 无法完成基本通信 从弹性云服务器内部ping所在子网的网关 无法ping通 则需首先排查二三层网络问题 本问题请按照以下思路进行排查处理 检查弹性云服务器是否获取到IP
  • vue---------商城pc端 购物车模块

    目录 uuid some 与 every switch语句 HTTP的8种请求方式 Promise all的用法及其细节 uuid uuid生成随机id npm install uuid 下载 生成随机且唯一的游客身份 import v4
  • ERC20 协议

    https www jb51 net blockchain 797814 html https blog csdn net bareape article details 124275062 代币标准 ERC20协议源码解析 我们在买入US
  • 【华为OD机试真题】简单的自动曝光(C++&java&python)100%通过率 超详细代码注释 代码优化

    华为OD机试真题 2022 2023 真题目录 点这里 华为OD机试真题 信号发射和接收 试读 点这里 华为OD机试真题 租车骑绿道 试读 点这里 简单的自动曝光 时间限制 1s 空间限制 256MB 限定语言 不限 题目描述 一个图像有n
  • Android系统开发篇(二) —— 建立Android系统开发环境之Ubuntu 20.04.4 LTS

    书接上文 上文中我们主要介绍了虚拟机环境的搭建 那么接下来我们继续还是来说说Android系统开发环境的搭建 Ubuntu系统的安装和配置 上文我们说到虚拟机的新建了且已经搭载了Ubuntu 20 04 4LTS系统 当然你也可以选择搭载其
  • [剑指Offer] 5 替换空格

    目录 题目 5 替换空格 描述 思路 代码实现 相关题目 合并两个排序数组到其中一个数组中 描述 思路 代码实现 题目 5 替换空格 描述 请实现一个函数 把字符串中的每个空格替换成 20 示例 输入 We are happy 输出 We