算法通关村——字符串反转问题解析

字符串反转问题

我们知道反转是链表的一个重要考点,反转同样是字符串的重要问题。字符串和链表在处理反转的方式上有相似的地方,一般都是运用双指针,一个指针从前找,一个指针从后找。具体的处理办法结合下面具体的题目来看:

1、反转字符串

LeetCode344. 编写一个函数,其作用是将输入的字符串反转过来。输入字符串以字符数组s的形式给出。不要给另外的数组分配额外的空间,你必须原地修改输入数组、使用O(1)的额外空间来解决这一问题。

示例:

输入:s = [“h”, “e”, “l”, “l”, “o”]

输出:[“o”, “l”, “l”, “e”, “h”]

这是最基本的反转问题,也是最简单的问题,使用双指针方法最直接。具体做法是:

  • 将left 指向字符数组首元素,right指向字符数组尾元素
  • 当left < right时:
    • 交换s[left] 和 s[right]
    • left指针向右移一位
    • right指针向左移一位
  • 当left>=right时,反转结束,返回字符数组

具体的java代码如下:

public void reverseString(char[] s) {
    if (s == null || s.length() == 0) {
        return;
    }
    int n = s.length;
    for (int left = 0, right = n - 1; left < right; left++, right++) {
        char temp = s[left];
        s[left] = s[right];
        s[right] = temp;
    }
}

2、K个一组反转

LeetCode541. 给定一个字符串s和一个整数k,从字符串开头算起,每计数至2k个字符,就反转这2k字符中的前k个字符。

  • 如果剩余字符少于k个,则将剩余字符全部反转。
  • 如果剩余字符小于2k但大于或等于k个,则反转前k个字符,其余字符保持原样。

示例1:

输入:s = “abcdefg”, k = 2

输出:“bacdfeg”

示例2:

输入:s = “abcd”, k = 2

输出:“bacd”

对于这题,只用按照题意来就好了:反转每个下标从2k的倍数开始的,长度为k的子串。若该子串长度不足k,则反转整个子串。

public String reverseStr(String s, int k) {
    if (s == null || s.length() == 0) {
        return s;
    }
    int n = s.length();
    char[] arr = s.toCharArray();
    for (int i = 0; i < n; i += 2 * k) {
        reverse(arr, i, Math.min(i + k, n) - 1);
    }
    return new String(arr);
}

public void reverse(char[] arr, int left, int right) {
    while (left < right) {
        char temp = arr[left];
        arr[left] = arr[right];
        arr[right] = temp;
        left++;
        right--;
    }
}

3、仅仅反转字母

LeetCode917. 给定一个字符串S,返回”反转后的”字符串,其中不是字母的字符都保留在原地,而所有字母的位置发生反转。

示例1:

输入:“ab-cd”

输出:“dc-ab”

示例2:

输入:“a-bC-dEf-ghIj”

输出:“j-Ih-gfE-dCba”

示例3:

输入:“Test1ng-Leet=code-Q!”

输出:“Qedo1ct-eeLg=ntse-T!”

这题的难点主要在需要反转的段的划分不均匀,也就是非字母的字符出现在字符串中的位置是随机的。可以考虑用以下两种方法来做:

方法1:使用栈

将s中的所有字母单独存入栈中,所以出栈等价于对字母反序操作。然后,遍历s的所有字符,如果是字母我们就选择栈顶元素输出,不是字母就输出s的字符。代码如下:

public String reverseOnlyLetters(String s) {
    Stack<Character> letters = new Stack();
    for (char c : S.toCharArray()) {
        if (Character.isLetter(c)){
            letters.push(c);
        }
    }
    
    StringBuilder ans = new StringBuilder();
    for (char c :S.toCharArray()) {
        if (Character.isLetter(c)) {
            ans.append(letters.pop());
        } else {
            ans.append(c);
        }
    }
    
    return ans.toString();
}

方法2:拓展 双旋指针

一个接一个输出s的所有字符。当遇到一个字母时,我们希望找到逆序遍历字符串的下一个字母。所以我们可以维护一个指针j从后往前遍历字符串,当需要字母时就使用它。代码如下:

public String reverseOnlyLetters(String s) {
    if (s == null || s.length() == 0) {
        return s;
    }
    StringBuilder ans = new StringBuilder();
    int j = s.length() - 1;
    for (int i = 0; i < s.length(); i++) {
        if (Character.isLetter(s.chatAt(i))) {
            while (!Character.isLetter(s.char)){
                j--;
            }
            ans.append(s.charAt(j--));
        } else {
            ans.append(s.chatAt(i));
        }
    }
    return ans.toString();
}

4、反转字符串里的单词

LeetCode151. 给你一个字符串,逐个反转字符串中的所有 单词

单词是由非空格字符组成的字符串。s中至少一个空格将字符串中的单词分隔开。

请你返回一个反转s中单词顺序并用单个空格相连的字符串。

说明:

  • 输入字符串s可以在前面、后面或者单词间包含多余的空格。
  • 反转后的单词间应当仅用一个空格分隔。
  • 反转后的字符串中不应包含额外的空格。

示例:

输入:s = “the sky is blue”

输出:s = “blue is sky the”

在java语言中对字符串提供了split(拆分),reverse(反转)和join(连接)等方法,因此我们可以简单的调用内置的API来完成操作:

  • 使用split将字符串按空格分割成字符串数组
  • 使用reverse将字符串数组进行反转
  • 使用join方法将字符串数组拼成一个字符串

如图:

image-20231117222742177

public String reverseWords(String s) {
    if (s == null || s.length() == 0) {
        return s;
    }
    //除去开头和末尾的空白字符
    s = s.trim();
    //正则匹配连续的空白字符作为分隔符分割
    List<String> wordList = Arrays.asList(s.split("\\s+"));
    Collections.reverse(wordList);
    return String.join(" ", wordList);
}

如果不使用语言自己的提供的方法,也可以完成这一题。

方法流程如下:

image-20231117223155604

代码如下:

public static String reverseWords(String s) {
    StringBuilder sb = trimSpaces(s);

    // 翻转字符串
    reverse(sb, 0, sb.length() - 1);
    // 翻转每个单词
    reverseEachWord(sb);
    return sb.toString();
}

public static StringBuilder trimSpaces(String s) {
    int left = 0, right = s.length() - 1;
    // 去掉字符串开头的空白字符
    while (left <= right && s.charAt(left) == ' ') {
        ++left;
    }

    // 去掉字符串末尾的空白字符
    while (left <= right && s.charAt(right) == ' ') {
        --right;
    }

    // 将字符串间多余的空白字符去除
    StringBuilder sb = new StringBuilder();
    while (left <= right) {
        char c = s.charAt(left);

        if (c != ' ') {
            sb.append(c);
        } else if (sb.charAt(sb.length() - 1) != ' ') {
            sb.append(c);
        }
        ++left;
    }
    return sb;
}

public static void reverse(StringBuilder sb, int left, int right) {
    while (left < right) {
        char tmp = sb.charAt(left);
        sb.setCharAt(left++, sb.charAt(right));
        sb.setCharAt(right--, tmp);
    }
}

public static void reverseEachWord(StringBuilder sb) {
    int n = sb.length();
    int start = 0, end = 0;

    while (start < n) {
        // 循环至单词的末尾
        while (end < n && sb.charAt(end) != ' ') {
            ++end;
        }
        // 翻转单词
        reverse(sb, start, end - 1);
        // 更新start,去找下一个单词
        start = end + 1;
        ++end;
    }
}

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

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

相关文章

深度学习入门(第三天)——卷积神经网络

一、卷积神经网络应用领域 CV领域发展&#xff1a; 比赛中预测错误率的百分比&#xff0c;每年逐步下降。Human是人类肉眼的识别能力&#xff0c;2016年开始已经远高于人类肉眼死别能力&#xff0c;后面就取消了该方向的比赛了。 检测任务&#xff1a; 分类与检索&#xff1a;…

【Linux】重定向|重新理解Linux下一切皆文件

文章目录 一、什么是重定向输出重定向的原理认识一下输出重定向的系统调用输出重定向的另外写法 二、浅谈输入重定向三、重定向和进程替换有冲突吗四、Linux下一切皆文件总结 一、什么是重定向 理解重定向之前&#xff1a;先理解一个叫做文件描述符的具体操作。 文件描述符&a…

信创之路数据库人大金仓篇

概要 信创大势所趋&#xff0c;吾等上下求索 参考文档 Linux&#xff1a;人大金仓数据库-KingBaseES V8与 php7的连接配置 laravel9适配人大金仓&#xff08;kingbase&#xff09;数据库 thinkphp6适配人大金仓&#xff08;Kingbase&#xff09;数据库 数据库选型 目前比较…

C语言--统计一行字符串的单词个数, 单词用非字母分割.例如“ab235adg 456ad“被认为是3个单词.

一.题目描述 统计一行字符串的单词个数, 单词用非字母分割. 例如"ab235adg 456ad"被认为是3个单词. 二.思路分析 本题的主要难点在于如何判断有一个单词呢&#xff0c;当然遍历字符串是必须的。下面给出两种不同的思路&#xff1a; 一.当前是字母&#xff0c;下一个…

openRPA开源项目源码编译

最近接触到了一个新的领域——RPA&#xff0c;RPA全称Robotic Process Automation&#xff0c;中文名为机器人流程自动化。RPA可以视作一个数字机器人&#xff0c;它可以通过程序来模拟人与软件系统的交互过程&#xff0c;代替人工将大量重复、有规则的计算机操作自动化&#x…

Vite -静态资源处理 - SVG格式的图片

特点 Vite 对静态资源是开箱即用的。 无需做特殊的配置。项目案例 项目结构 study-vite| -- src| -- assets| -- bbb.svg # 静态的svg图片资源| -- index.html # 主页面| -- main.js # 引入静态资源| -- package.json # 脚本配置| -- vite.co…

3GPP TS38.201 NR; Physical layer; General description (Release 18)

TS38.201是介绍性的标准&#xff0c;简单介绍了RAN的信道组成和PHY层承担的功能&#xff0c;下图是PHY层相关标准的关系。 文章目录 结构信道类型调制方式PHY层支持的过程物理层测量其他标准TS 38.202: Physical layer services provided by the physical layerTS 38.211: Ph…

【Mac开发环境搭建】Docker安装Redis、Nacos

文章目录 Dokcer安装Redis拉取镜像创建配置文件创建容器连接测试Redis连接工具[Quick Redis]设置Redis自启动 Docker安装Nacos Dokcer安装Redis 拉取镜像 docker pull redis创建配置文件 # bind 127.0.0.1 -::1 bind 0.0.0.0 # 是否启用保护模式 protected-mode no# redis端口…

python+pytest接口自动化测试之接口测试基础

一、接口测试的基本信息 1、常用的两种接口&#xff1a;webservice接口和http api接口   webService接口是走soap协议通过http传输&#xff0c;请求报文和返回报文都是xml格式的&#xff0c;可以用soupui、jmeter等工具进行测试。   http api接口是走http协议&#xff0c;…

数据结构与算法之美学习笔记:20 | 散列表(下):为什么散列表和链表经常会一起使用?

目录 前言LRU 缓存淘汰算法Redis 有序集合Java LinkedHashMap解答开篇 & 内容小结 前言 本节课程思维导图&#xff1a; 今天&#xff0c;我们就来看看&#xff0c;在这几个问题中&#xff0c;散列表和链表都是如何组合起来使用的&#xff0c;以及为什么散列表和链表会经常…

【咖啡品牌分析】Google Maps数据采集咖啡市场数据分析区域分析热度分布分析数据抓取瑞幸星巴克

引言 咖啡作为一种受欢迎的饮品&#xff0c;已经成为我们生活中不可或缺的一部分。随着国内外咖啡品牌的涌入&#xff0c;新加坡咖啡市场愈加多元化和竞争激烈。 本文对新加坡咖啡市场进行了全面的品牌门店数占比分析&#xff0c;聚焦于热门品牌的地理分布、投资价值等。通过…

系列四、GC垃圾回收【四大垃圾算法-引用计数法】

一、概述 Java中&#xff0c;引用和对象是有关联的&#xff0c;如果要操作对象则必须要用引用进行。因此判断一个对象是否可以被回收&#xff0c;很显然一个简单的办法就是通过引用计数来判断一个对象是否可以被回收。简单来讲就是给对象中添加一个引用计数器&#xff0c;每当一…

echarts 实现双y轴折线图示例

该示例有如下几个特点&#xff1a; ①实现tooltip自定义样式&#xff08;echarts 实现tooltip提示框样式自定义-CSDN博客&#xff09; ②legend左右区分展示 ③双y轴折线展示 代码如下&#xff1a; this.options {grid: {left: "3%",right: "3%",top: &…

目标检测—YOLO系列(二 ) 全面解读论文与复现代码YOLOv1 PyTorch

精读论文 前言 从这篇开始&#xff0c;我们将进入YOLO的学习。YOLO是目前比较流行的目标检测算法&#xff0c;速度快且结构简单&#xff0c;其他的目标检测算法如RCNN系列&#xff0c;以后有时间的话再介绍。 本文主要介绍的是YOLOV1&#xff0c;这是由以Joseph Redmon为首的…

测试开发环境下centos7.9下安装docker的minio

按照以下方法进行 1、安装docker&#xff0c;要是生产等还是要按照docker-ce yum install docker 2、启动docker service docker start 3、 查看docker信息 docker info 4、加到启动里 systemctl enable docker.service 5、开始docker pull minio/minio 但报错&#x…

【2023春李宏毅机器学习】快速了解机器学习基本原理

文章目录 机器学习约等于机器自动找一个函数 机器学习分类 regression&#xff1a;输出为连续值classification&#xff1a;输出为一个类别structured learning&#xff1a;又叫生成式学习generative learning 生成有结构的物件&#xff08;如&#xff1a;影像、句子&#xf…

Facebook内容的类型

随着人们日益依赖的社交媒体来进行信息获取与交流&#xff0c;Facebook作为全球最大的社交媒体平台之一&#xff0c;那么Facebook的内容都有哪些类型呢&#xff1f;下面小编来讲讲吧&#xff01; 1、实时发生的事 我们需要实时了解时事动态&#xff0c;这样可以使用户对品牌发…

CAN总线负载及CANoe查看总线负载率

文章目录 一、什么是CAN总线的负载率&#xff1f;二、负载率计算三、CANoe查看总线负载率 一、什么是CAN总线的负载率&#xff1f; 一般业内对负载率的定义为&#xff1a;实际数据传输速率和理论上能达到的数据传输速率的比值。 传输速率一般是按秒来计算&#xff0c;数据传输…

Shopee买家通系统是怎么操作自动下单的

Shopee买家通系统可以自动下单虾皮平台的产品&#xff0c;具体操作流程是先准备好能下单的账号&#xff08;没有账号可以直接准备资料后用软件进行注册&#xff09;&#xff0c;然后设置关键词及产品编号进行自动搜索、点击、浏览后进行添加购物车&#xff0c;最后再进行自动结…

自学人工智能难吗?

在人工智能风靡全球的时代&#xff0c;越来越多的人对学习人工智能产生了浓厚的兴趣。那么&#xff0c;自学人工智能难吗&#xff1f;今天&#xff0c;我们将为你揭开这个谜团&#xff0c;让你轻松开启智能未来之旅&#xff01; 一、自学人工智能——不再是难题 过去&#xf…