算法之常见字符串题目

news2024/11/26 2:04:35

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

示例 1:

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

示例 2:

输入:s = [“H”,“a”,“n”,“n”,“a”,“h”] 输出:[“h”,“a”,“n”,“n”,“a”,“H”]

方法一、双指针

// 第一种方法用temp来交换数值更多人容易理解些
class Solution {
    public void reverseString(char[] s) {
        int l = 0;
        int r = s.length - 1;
        while(l < r){
            char temp = s[l];
            s[l] = s[r];
            s[r] = temp;
            l++;
            r--;
        }
    }
}

方法二、位运算

class Solution {
    public void reverseString(char[] s) {
        int l = 0;
        int r = s.length - 1;
        while (l < r) {
            s[l] ^= s[r];  //构造 a ^ b 的结果,并放在 a 中
            s[r] ^= s[l];  //将 a ^ b 这一结果再 ^ b ,存入b中,此时 b = a, a = a ^ b
            s[l] ^= s[r];  //a ^ b 的结果再 ^ a ,存入 a 中,此时 b = a, a = b 完成交换
            l++;
            r--;
        }
    }
}

leedcode541. 反转字符串 II
给定一个字符串 s 和一个整数 k,从字符串开头算起,每计数至 2k 个字符,就反转这 2k 字符中的前 k 个字符。
如果剩余字符少于 k 个,则将剩余字符全部反转。
如果剩余字符小于 2k 但大于或等于 k 个,则反转前 k 个字符,其余字符保持原样。

示例 1:

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

示例 2:

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

class Solution {
    //满足一下条件
    //1.从字符串开头算起,每计数至2k个字符,就反转2k个字符中的前k个字符。
    //2.如果字符小于2k个但大于等于k个则反转前k个,其余字符串保存不变
    //3.如果字符少于k个,则将剩余字符全部反转
    //仔细观察第2个条件其实和第一个条件可以同时处理
    public String reverseStr(String s, int k) {
        char[] ch=s.toCharArray();
        for(int i=0;i<ch.length;i=i+2*k){
            //完成第1个和第二个条件
            if(i+k<=ch.length){ //防止加到后面超出范围,至于是<=可以带个数字进行,例如abc,此时i=0指向a,length是3,k是3,满足条件2需要进行反转
                //进行反转
               reserve(ch,i,i+k-1);//i+k-1是因为i从0开始然后reserve中i到i+k-1是左闭右闭
               continue;//进行下一轮循环
            }
            //如果剩余字符小于k的话
            reserve(ch,i,ch.length-1);//反转全部
        }
        //将字符数组转成字符串
        return new String(ch);

       
    }
    //自定义反转函数
    public void reserve(char[] s,int left,int right){
        while(left<right){
        char temp=s[left];
        s[left]=s[right];
        s[right]=temp;
        left++;
        right--;
        }
     
    }
}

leedcode151. 反转字符串中的单词
给你一个字符串 s ,请你反转字符串中 单词 的顺序。
单词 是由非空格字符组成的字符串。s 中使用至少一个空格将字符串中的 单词 分隔开。
返回 单词 顺序颠倒且 单词 之间用单个空格连接的结果字符串。
注意:输入字符串 s中可能会存在前导空格、尾随空格或者单词间的多个空格。返回的结果字符串中,单词间应当仅用单个空格分隔,且不包含任何额外的空格。

示例 1:

输入:s = “the sky is blue” 输出:“blue is sky the”

示例 2:

输入:s = " hello world " 输出:“world hello”

解释:反转后的字符串中不能存在前导空格和尾随空格。

示例 3:
输入:s = “a good example” 输出:“example good a”
解释:如果两个单词间有多余的空格,反转后的字符串需要将单词间的空格减少到仅有一个。

class Solution {
   //原字符串:" hello world "
   //删除多余空格:"hello world"
   //字符串反转:"dlrow olleh"
   //单词反转:"world hello" 
    public String reverseWords(String s) {
         char[] chars=s.toCharArray();
         //去除首尾和中间多余的空格
          char[] newchar=removeExtraSpaces(chars);
         //反转字符串
         reserve(newchar,0,newchar.length-1);
         //单词反转
         reserveWord(newchar);
         return new String(newchar);

         
    }
    //和数组中移除元素的双指针方法很像
    public char[] removeExtraSpaces(char[] chars){
        //定义慢指针用于更新元素
        int slow=0;
        for(int hight=0;hight<chars.length;hight++){
            //通过快指针来判断出空格的位置,然后让慢指针来判断是否对其添加空格
            if(chars[hight]!=' '){//说明到下一个单词
               //因为首个位置不能是空格
               if(slow!=0){
                  chars[slow]=' ';//此时快指针指向的不是空格,慢指针指向的字符增加一个空格
                  slow++;//同时移动慢指针
               }
               //因为要hight++所以要判断hight<chars.length,当快指针不执行空格,快慢指针同时移动
             while(hight<chars.length&&chars[hight]!=' '){
                chars[slow]=chars[hight];
                slow++;
                hight++;
            }
            }
        }
        //复制数组,新建一个数组,将chars[slow]的元素复制过来
       char[] newchar= new char[slow];//slow刚好是多移出1位,所以数组长度是slow
       /**
       第一个参数是要被复制的数组
       第二个参数是被复制的数字开始复制的下标
       第三个参数是目标数组,也就是要把数据放进来的数组
       第四个参数是从目标数据第几个下标开始放入数据
       第五个参数表示从被复制的数组中拿几个数值放到目标数组中
        */
       System.arraycopy(chars,0,newchar,0,slow);
       return newchar;
    }
    //反转字符串
    public void reserve(char[] chars,int left,int right){
         if (right >= chars.length) {
            System.out.println("set a wrong right");
            return;
        }
        while(right>left){
            //方法一
            // chars[left]^=chars[right];
            // chars[right]^=chars[left];
            // chars[left]^=chars[right];
            //方法二
            char temp=chars[left];
            chars[left]=chars[right];
            chars[right]=temp;
            left++;
            right--;
        }
    }
    //反转单词
    public void reserveWord(char[] chars){
        int start=0;
        //end <= s.length() 这里的 = ,是为了让 end 永远指向单词末尾后一个位置,这样我们最后能对start到end-1进行反转
        for(int end=0;end<=chars.length;end++){
            if(end==chars.length||chars[end]==' '){
                 end 每次到单词末尾后的空格或最后一个单词的后面,开始反转单词
                reserve(chars,start,end-1);
                //start位置为end位置加1比如end为空格位置,start就为空格的后一个字符
                start=end+1;
            }
        }
    }

}

剑指 Offer 58 - II. 左旋转字符串
字符串的左旋转操作是把字符串前面的若干个字符转移到字符串的尾部。请定义一个函数实现字符串左旋转操作的功能。比如,输入字符串"abcdefg"和数字2,该函数将返回左旋转两位得到的结果"cdefgab"。

示例 1:

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

示例 2:

输入: s = “lrloseumgh”, k = 6 输出: “umghlrlose”

示例 1:
在这里插入图片描述
在这里插入图片描述

class Solution {
    /**abcdefg   k = 2
    1.反转区间为前n的子串ba cdefg
    2.反转区间为n到末尾的子串ba gfedc
    3.反转整个字符串 cdefgab
    */
    public String reverseLeftWords(String s, int n) {
         char[] chars=s.toCharArray();
         reserve(chars,0,n-1);
         reserve(chars,n,chars.length-1);
         reserve(chars,0,chars.length-1);
         return new String(chars);

    }
    public void reserve(char[] chars,int left,int right){
        while(left<right){
            chars[left]^=chars[right];
            chars[right]^=chars[left];
            chars[left]^=chars[right];
            left++;
            right--;
        }

    }
}

leedcode459. 重复的子字符串
给定一个非空的字符串 s ,检查是否可以通过由它的一个子串重复多次构成。

示例 1:

输入: s = “abab” 输出: true 解释: 可由子串 “ab” 重复两次构成。

示例 2:

输入: s = “aba” 输出: false

示例 3:

输入: s = “abcabcabcabc” 输出: true 解释: 可由子串 “abc” 重复四次构成。 (或子串 “abcabc”
重复两次构成。)

方法一:移动匹配

class Solution {
    //移动匹配
    //判断字符串s是否由重复子串组成,只要两个s拼接在一起,里面还出现一个s的话,就说明是由重复子串组成。
    public boolean repeatedSubstringPattern(String s) {
       String t=s+s;
       //字符串截取substring是左闭右开的原则
    //我们在判断 s + s 拼接的字符串里是否出现一个s的的时候,要刨除 s + s 的首字符和尾字符,
    //这样避免在s+s中搜索出原来的s,我们要搜索的是中间拼接出来的s
       if(t.substring(1,t.length()-1).contains(s)){
           return true;
       }else{
           return false;
       }

    }
}

方法二:KMP

class Solution {
    //kmp算法,因为最长相等前后缀的规则,当一个字符串由重复子串组成的,最长相等前后缀不包含的子串就是最小重复子串
    public boolean repeatedSubstringPattern(String s) {

        if(s.length()==0){
            return false;
        }
        int[] next=new int[s.length()];
        //获取next数组,也就是最长相等前后缀
        getNext(next,s);
        //如果s.length()%(s.length()-next[s.length()-1])==0,则说明数组的长度正好可以被 (数组长度-最长相等前后缀的长度) 整除,说明该字符串有重复的子字符串。
        if(next[s.length()-1]!=0&&s.length()%(s.length()-next[s.length()-1])==0){
            return true;
        }
        return false;
    }
    public void getNext(int[] next,String s){
        //初始化
        int j=0;
        next[0]=0;
        for(int i=1;i<s.length();i++){
            while(j>0&&s.charAt(i)!=s.charAt(j)){
              //回退
              j=next[j-1];
            }
            if(s.charAt(i)==s.charAt(j)){
               j++;
            }
            next[i]=j;
        }
    }
}

小明的字符串
小明有两个字符串,分别为 S,TS,T。
请你求出 TT 串的前缀在 SS 串中出现的最长长度为多少。
输入描述
输入包含两行,每行包含一个字符串,分别表示 S,T。保证 S,TS,T 只包含小写字母。
输出描述
输出共 11 行,包含一个整数,表示答案。
输入输出样例

示例 1
输入
aabba
abb
输出
3

示例 2
输入
aabba
aba
输出
2

使用KMP算法求得 TT 串的前缀在 SS 串中出现的最长长度

public class KmpTest {
   static int sum=0;
   static  int[] next=new int[1000000];
    public static void main(String[] args) {
        Scanner scan = new Scanner(System.in);
        String s1 = scan.next();
        String s2 = scan.next();

        getNext(next,s2);
        Kmp(s1,s2);
        System.out.println(sum);
    }

    private static void Kmp(String s1, String s2) {
        int j=0;
        for(int i=0;i<s1.length();i++){
            while(j>0&&s1.charAt(i)!=s2.charAt(j)){
                j=next[j-1];
            }
            if(s1.charAt(i)==s2.charAt(j)){
                j++;
            }
            //当j最长也就是 TT 串在 SS 串中出现的最长长度
            sum=Math.max(j,sum);
            //当j如果完全满足等于s2的长度时要记得返回,不然i下次循环时比较j会越界
            if(j==s2.length()){
                return;
            }


        }
    }

    //求next数组获取最长相等前后缀
    private static void getNext(int[] next, String s2) {
        int j=0;
        next[0]=0;
        for(int i=1;i<s2.length();i++){
            while(j>0&&s2.charAt(i)!=s2.charAt(j)){
                j=next[j-1];
            }
            if(s2.charAt(i)==s2.charAt(j)){
                j++;
            }
            next[i]=j;

        }
    }
}

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

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

相关文章

进程学习笔记

进程 定义 一个程序程序在一个数据集合上的动态执行过程 与程序区别 动静&#xff0c;暂时的过程和永久的存在&#xff0c;进程由程序、数据、进程控制块&#xff08;PCB&#xff09;组成 特性 动态并发&#xff08;进程&#xff09;独立&#xff08;分页有力支持&#x…

Linux:C/C++文件操作

回忆C语言文件操作 fopen()的使用&#xff1a;   答&#xff1a;打开文件流指针。 param2 “w”&#xff0c;当前没有文件就先创建&#xff0c;再写入。 “r”&#xff0c;只读。 “b”&#xff0c;可与w、b组合。 只写的例子&#xff1a; 只读的例子&#xff1a; 依靠fg…

《Linux性能优化实战》学习笔记 Day01

学习目标 系统优化的旅程上&#xff0c;对操作系统相关的优化是绕不开的&#xff0c;主动出击&#xff0c;将零星的知识体系化。今后遇到问题&#xff0c;能够加入自己的体系树中&#xff0c;即使专栏中没有提到&#xff0c;自己也能够想办法深入。 希望在这次课程后&#xf…

黑马Redis | 基础篇

目录 一、SQL和NoSQL的区别 结构化与非结构化 关联和非关联 查询方式 事务 总结 二、Redis数据类型和命令 1、通用命令 2、数据类型 3、String类型 String的常见命令 Key结构 4、Hash类型 常见命令 5、List类型 6、Set类型 Set的常见命令 7、SortedSet类型 …

科研快报|PacBio全长扩增子测序破解蚊子肠道微生态与耐药性差异

论文题目&#xff1a;Differences in the intestinal microbiota between insecticide-resistant and -sensitive Aedes albopictus based on full-length 16S rRNA sequencing.期刊&#xff1a;Microbiologyopen影响因子&#xff1a;3.139发表时间&#xff1a;2021年1月研究背…

一个非常好用的中奖概率控制器

本文首发于微信公众号&#xff1a; 小蚂蚁教你做游戏。欢迎关注领取更多学习做游戏的原创教程资料&#xff0c;每天学点儿游戏开发知识。嗨&#xff01;大家好&#xff0c;我是小蚂蚁。今天分享一个非常好用的概率控制器&#xff0c;可以用于游戏中两种行为出现的概率控制。这个…

PHP MySQL 插入数据

使用 MySQLi 和 PDO 向 MySQL 插入数据 在创建完数据库和表后&#xff0c;我们可以向表中添加数据。 以下为一些语法规则&#xff1a; PHP 中 SQL 查询语句必须使用引号在 SQL 查询语句中的字符串值必须加引号数值的值不需要引号NULL 值不需要引号 INSERT INTO 语句通常用于…

《Linux Shell脚本攻略》学习笔记-第十三章

13.1 简介 现代Linux应用可以部署在专门的硬件、容器、虚拟机或是云端。 容器的缺点在于它以来于主机的系统内核。 虚拟机的防在于要占用大量的磁盘空间。 如果你想同时运行多个虚拟机&#xff0c;必须要有足够的内存来支撑各个虚拟机。否则&#xff0c;主机就不得不开始交换页…

SLS:基于 OTel 的移动端全链路 Trace 建设思考和实践

作者&#xff1a;高玉龙 (元泊)首先&#xff0c;我们了解一下移动端全链路 Trace 的背景&#xff1a;从移动端的视角来看&#xff0c;一个 App 产品从概念产生&#xff0c;到最终的成熟稳定&#xff0c;产品研发过程中涉及到的研发人员、工程中的代码行数、工程架构规模、产品发…

探索VGG网络与LeNet网络对精度的影响

1 问题在学习不同网络模型对实验精度的影响过程中&#xff0c;对我们的实验结果&#xff0c;各种参数数值的改变有何变化&#xff0c;有何不同。VGG-11网络与LeNet-5网络对精度和损失的影响研究。训练周期20其他参数都相同的方式来探索最终的精度。2 方法对于VGG-11网络&#x…

QTreeWidget 设置任意行背景色

设置任意某行&#xff0c;网上这类示例少&#xff0c;一般都是选中行、交替行、高亮行等设置。 比如我要将顶层节点的背景色修改一下。 方法1&#xff0c;先继承QTreeWidget,更改它的 drawBranches函数&#xff0c;在里面添加条件判断&#xff0c;然后根据需要设置颜色。 #i…

【计算机体系结构-01】指令集体系结构、微体系结构简介

1. “虚拟” to “现实” 首先可以看这张图片&#xff0c;下面的 Physics 所指的是我们的物理世界中看得见摸得到或者是客观存在的事物&#xff0c;而人类希望将自己的工作内容或者需求以某种方式映射到物理层面上&#xff0c;用物理变化带来的影响来完成人类工作内容。例如早期…

Python【r e】模块正则表达式[中]实战

正则表达式相关函数和符号用法&#xff1a;#正则表达式""".匹配任意某个字符[.]与转义字符的作用一致&#xff0c;表示匹配.,配合 &#xff0c;[.],即匹配一次或则多次. text . 或则 text ...2.从头匹配或者从左往右匹配re.match()"""import …

IDEA整合Docker,一键打包服务镜像与启动容器

尝试了IDEA整合Docker&#xff0c;坑有些多&#xff0c;但经过查阅资料都一一解决了&#xff0c;写了个案例&#xff0c;感觉这种方式确实要方便很多。下面来整理下步骤&#xff1a; 一、安装Docker 准备一台Linux&#xff0c;我这里用的是centos 7 mini 版&#xff0c;然后安…

内网穿透的概念及解决方案

1.什么是内网穿透 在外网的web请求可以转发到内网的本地服务 2.什么是内网&#xff1f;什么是外网&#xff1f; 内网(也叫局域网(Local Area Network&#xff0c;LAN))是在一个局部的地理范围内&#xff0c;一般可以是是几米内(比如家庭内网)&#xff0c;也可以是方圆几千米…

2023 年 10 大最佳 GIS 软件

有人说&#xff1a;一个人从1岁活到80岁很平凡&#xff0c;但如果从80岁倒着活&#xff0c;那么一半以上的人都可能不凡。 生活没有捷径&#xff0c;我们踩过的坑都成为了生活的经验&#xff0c;这些经验越早知道&#xff0c;你要走的弯路就会越少。 GIS 是一个分析地理相关性…

【算法】拓扑排序

目录1.概述2.代码实现3.应用本文参考&#xff1a; LABULADONG 的算法网站 1.概述 &#xff08;1&#xff09;拓扑排序 (Topological Sort) 是指将有向无环图 G (V, E) 中所有顶点排成一个线性序列&#xff0c;使得图中任意一对顶点 u 和 v&#xff0c;若边<u, v> ∈ E(…

esp32 使用u8g2图形库 IIC驱动OLED

简介&#xff1a;使用U8g2库进行OLED的显示十分简单&#xff0c;首先要包含两个库&#xff0c;U8g2lib和Wire&#xff0c;后者是IIC通信需要用。对于IIC接口的OLED&#xff0c;需要在程序中指定一下引脚的接口定义&#xff0c;如果是SPI接口&#xff0c;可以参考U8g2库自带例程…

【Leetcode】NC31 第一个只出现一次的字符(牛客网)、面试题 01.01. 判定字符是否唯一

作者&#xff1a;一个喜欢猫咪的的程序员 专栏&#xff1a;《Leetcode》 喜欢的话&#xff1a;世间因为少年的挺身而出&#xff0c;而更加瑰丽。 ——《人民日报》 NC31 第一个只出现一次的字符 第一个只出现一次的字符_牛客题霸_牛客网【牛…

数据结构与算法(三)——顺序查找和二分查找

什么是查找 在一些数据元素中&#xff0c;通过一定的方法找出与给定关键字相同的数据元素的过程。 什么是列表查找 也叫线性表查找&#xff0c;从列表中查找指定元素 列表查找是一种算法&#xff0c;对应的自然就有输入和输出&#xff1a; 输入&#xff1a;列表、待查找元素…