代码随想录 字符串 Java

news2024/10/6 6:04:08

文章目录

  • (简单)344. 反转字符串
  • (简单)541. 反转字符串||
  • (简单)剑指Offer 05. 替换空格
  • (中等)151. 反转字符串中的单词
  • (简单)剑指 Offer 58 - II. 左旋转字符串
  • (*中等 - KMP算法)28. 找出字符串中第一个匹配项的下标
  • (*简单 - KMP算法)459. 重复的子字符串


(简单)344. 反转字符串

在这里插入图片描述

class Solution {
    public void reverseString(char[] s) {
        int left = 0;
        int right = s.length - 1;
        while (left < right) {
            char tmp = s[left];
            s[left] = s[right];
            s[right] = tmp;
            left++;
            right--;
        }
    }
}

复杂度分析:

  • 时间复杂度:O(N),其中N为字符数组的长度。一共执行了N/2次的交换
  • 空间复杂度:O(1),只使用了常数空间来存放若干变量

(简单)541. 反转字符串||

在这里插入图片描述
我的思路:2k个字符为一组,先将前k个字符(或者不足k个字符)添加到StringBuilder中,然后调用reverse()方法,然后再将后k个字符(或者不足2k个字符)添加到StringBuilder中,最后在将这一组作为一个整体,添加到答案中

class Solution {
    public String reverseStr(String s, int k) {
        int n = s.length();
        int i = 0;
        StringBuilder stringBuilder = new StringBuilder();
        while (i < n) {
            StringBuilder strk = new StringBuilder();
            while (i < n && strk.length() < k) {
                strk.append(s.charAt(i));
                i++;
            }
            strk.reverse();
            while (i < n && strk.length() >= k && strk.length() < 2 * k) {
                strk.append(s.charAt(i));
                i++;
            }
            stringBuilder.append(strk);
        }
        return stringBuilder.toString();
    }
}

在这里插入图片描述
我的另一种思路:将字符串s转换成字符数组,然后在字符数组中找到合适的区间进行交换

import java.util.regex.Pattern;

class Solution {
    public String reverseStr(String s, int k) {
        int n = s.length();
        char[] charArray = s.toCharArray();
        boolean flag = true;
        int i = 0;
        while (i < n) {
            if (flag) {
                int left = i;
                int right = i + k > n ? n - 1 : i + k - 1;
                while (left < right) {
                    char tmp = charArray[left];
                    charArray[left] = charArray[right];
                    charArray[right] = tmp;
                    left++;
                    right--;
                }
                i = i + k;
                flag = false;
            } else {
                if (i + k >= n) {
                    break;
                } else {
                    i += k;
                    flag = true;
                }
            }
        }
        return new String(charArray);
    }
}

在这里插入图片描述
其他写法

也是模拟,反转每个下标从2k的倍数开始的,长度为k的子串。若该子串长度不足k,则反转整个子串。

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

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

在这里插入图片描述
复杂度分析:

  • 时间复杂度:O(n),其中n是字符串s的长度
  • 空间复杂度:O(1)和O(n),取决于使用的语言中字符串类型的性质。如果字符串是可修改的,可以直接在原字符串上进行修改,空间复杂度为O(1),否则需要使用O(n)的空间将字符串临时转换为可以修改的数据结构(例如数组),空间复杂度为O(n)。

(简单)剑指Offer 05. 替换空格

在这里插入图片描述

方法一

class Solution {
    public String replaceSpace(String s) {
        return s.replaceAll(" ", "%20");
    }
}

在这里插入图片描述
方法二

class Solution {
    public String replaceSpace(String s) {
        StringBuilder stringBuilder = new StringBuilder();
        for (int i = 0; i < s.length(); i++) {
            char c = s.charAt(i);
            if (c == ' ') {
                stringBuilder.append("%20");
            } else {
                stringBuilder.append(c);
            }
        }
        return stringBuilder.toString();
    }
}

在这里插入图片描述
其他思路

由于每次替换从1个字符变成3个字符,使用字符数组可方便地进行替换。建立字符数组的长度为s的长度的3倍,这样可保证字符数组可以容纳所有替换后的字符。

class Solution {
    public String replaceSpace(String s) {
        int n = s.length();
        char[] array = new char[n * 3];
        int index = 0;
        for (int i = 0; i < n; i++) {
            char c = s.charAt(i);
            if (c == ' ') {
                array[index++] = '%';
                array[index++] = '2';
                array[index++] = '0';
            } else {
                array[index++] = c;
            }
        }
        return new String(array, 0, index);
    }
}

在这里插入图片描述

(中等)151. 反转字符串中的单词

在这里插入图片描述

class Solution {
    public String reverseWords(String s) {
    	//使用trim()去掉首尾的空格,在使用split()按照" "分割
        String[] splits = s.trim().split(" ");
        StringBuilder stringBuilder = new StringBuilder();
        for (int i = splits.length - 1; i >= 0; i--) {
			//但单词间会有多个空格,遇到splits[i].length==0的直接跳过
            if (splits[i].length() == 0) {
                continue;
            }

            stringBuilder.append(splits[i]);

            if (i != 0) {
                stringBuilder.append(" ");
            }
        }
        return stringBuilder.toString();
    }
}

在这里插入图片描述
官方思路,方案一:使用语言特性

很多语言对字符串提供了split拆分、reverse翻转和join连接等方法,因此可以通过调用内置的API完成操作
在这里插入图片描述

import java.util.Arrays;
import java.util.Collections;
import java.util.List;

class Solution {
    public String reverseWords(String s) {
        s = s.trim();
        List<String> wordList = Arrays.asList(s.split("\\s+"));
        Collections.reverse(wordList);
        return String.join(" ", wordList);
    }
}

复杂度分析:

  • 时间复杂度:O(n),其中n为输入字符串的长度
  • 空间复杂度:O(n),用来存储字符串分割之后的结果

官方思路,方法二:自行编写相应的函数

在不同的编程语言中,这些函数是不一样的,主要的差别是有些语言的字符串不可变(如Python、Java),有些语言的字符串可变(如C++)。

对于字符串不可变的语言,首先得把字符串转化成其他可变的数据结构,同时还需要在转化的过程中去除空格。
在这里插入图片描述

对于字符串可变的语言,就不需要额外开辟空间了,直接在字符串上原地实现。在这种情况下,反转字符和去除空格可以一起完成。
在这里插入图片描述

class Solution {
    public String reverseWords(String s) {
        
        //去除首部、尾部、中间多余字符
        StringBuilder sb = trimSpace(s);
        
        //反转整个字符串
        reverse(sb, 0, sb.length() - 1);
        
        //以空格为分割,反转每一个单词
        reverseEachWord(sb);
        return sb.toString();
    }

    private void reverseEachWord(StringBuilder sb) {
        int start = 0;
        int end = 0;
        int n = sb.length();
        while (end < n) {
            while (end < n && sb.charAt(end) != ' ') {
                end++;
            }
            reverse(sb, start, end - 1);
            start = end + 1;
            end++;
        }
    }

    private 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);
            left++;
            right--;
        }
    }

    private StringBuilder trimSpace(String s) {
        int left = 0;
        int right = s.length() - 1;
        while (left <= right) {

            //去除字符串开头的空白字符串
            while (left <= right && s.charAt(left) == ' ') {
                left++;
            }

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

            StringBuilder stringBuilder = new StringBuilder();
            while (left <= right) {
                char c = s.charAt(left);
                if (c != ' ') {
                    stringBuilder.append(c);
                } else if (stringBuilder.charAt(stringBuilder.length() - 1) != ' ') {
                    stringBuilder.append(c);
                }
                left++;
            }
            return stringBuilder;
        }
        return null;
    }
}

在这里插入图片描述
复杂度分析:

  • 时间复杂度:O(n),其中n为输入字符串的长度,因为需要完整遍历字符串
  • 空间复杂度:Java和Python的方法需要O(n)的空间来存储字符出,而C++方法只需要O(1)的额外空间来存放若干变量

官方思路,方法三:双端队列

由于双端队列支持从队列头部插入的方法,因此我们可以沿着字符串一个一个单词处理,然后将单词压入队列头部,再将队列转成字符串即可

在这里插入图片描述

import java.util.ArrayDeque;
import java.util.Deque;

class Solution {
    public String reverseWords(String s) {
        int n = s.length();
        int left = 0;
        int right = s.length() - 1;

        //去除字符串开头的空白字符串
        while (left <= right && s.charAt(left) == ' ') {
            ++left;
        }

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

        Deque<String> deque = new ArrayDeque<>();
        StringBuilder word = new StringBuilder();

        while (left <= right) {
            char c = s.charAt(left);
            if (word.length() != 0 && c == ' ') {
                deque.offerFirst(word.toString());
                word.setLength(0);
            } else if (c != ' ') {
                word.append(c);
            }
            ++left;
        }
        deque.offerFirst(word.toString());

        return String.join(" ", deque);
    }
}

在这里插入图片描述
复杂度分析:

  • 时间复杂度:O(n),其中n为输入字符串的长度
  • 空间复杂度:O(n),双端队列存储单词需要O(n)的空间。

其实这个地方的双端队列和栈是一个意思啊

(简单)剑指 Offer 58 - II. 左旋转字符串

在这里插入图片描述
简单来说,就是把字符串截成两段,把这两段交换一下位置,拼接成一个新的字符串返回

class Solution {
    public String reverseLeftWords(String s, int n) {
        int len = s.length();
        char[] chars = new char[len];
        int index = 0;
        for (int i = n; i < len; i++) {
            chars[index++] = s.charAt(i);
        }
        for (int i = 0; i < n; i++) {
            chars[index++] = s.charAt(i);
        }
        return new String(chars);

    }
}

在这里插入图片描述

class Solution {
    public String reverseLeftWords(String s, int n) {

        int len = s.length();

        StringBuilder stringBuilder = new StringBuilder(len);

        for (int i = n; i < len; i++) {
            stringBuilder.append(s.charAt(i));
        }
        for (int i = 0; i < n; i++) {
            stringBuilder.append(s.charAt(i));
        }

        return stringBuilder.toString();

    }
}

在这里插入图片描述

(*中等 - KMP算法)28. 找出字符串中第一个匹配项的下标

在这里插入图片描述

最最最传统的字符串匹配问题,脑海中第一反应是KMP算法,但是不记得思路是啥了,所以写了暴力匹配法

class Solution {
    public int strStr(String haystack, String needle) {

        int n = needle.length();
        int h = haystack.length();

        if (n > h) {
            return -1;
        }

        int i = 0;
        int j;
        while (i < h) {
            if (haystack.charAt(i) != needle.charAt(0)) {
                i++;
            } else {
                int k = i + 1;
                j = 1;
                while (k < h && k < i + n && haystack.charAt(k) == needle.charAt(j)) {
                    k++;
                    j++;
                }
                if (k == i + n) {
                    return i;
                } else {
                    i++;
                }
            }
        }
        return -1;
    }
}

在这里插入图片描述

暴力法,就是让字符串needle与字符串haystack的所有长度为m的子串均匹配一次。

为了减少不必要的匹配,我们每次匹配失败即立刻停止当前子串的匹配,对下一个子串进行匹配。如果当前字串匹配成功,就返回当前子串开始的位置即可。如果所有子串都匹配失败,则返回-1

class Solution {
    public int strStr(String haystack, String needle) {

        int m = needle.length();//短的
        int n = haystack.length();//长的

        for (int i = 0; i + m <= n; i++) {
            boolean flag = true;
            for (int j = 0; j < m; j++) {
                if (haystack.charAt(i + j) != needle.charAt(j)) {
                    flag = false;
                    break;
                }
            }
            if (flag) {
                return i;
            }
        }
        return -1;
    }
}

在这里插入图片描述
复杂度分析:

  • 时间复杂度:O(nm),其中n是字符串haystack的长度,m是字符串needle的长度。最坏情况下需要将字符串needle与字符串haystack的所有长度为m的子串均匹配一次。
  • 空间复杂度:O(1),只需要常数的空间保存若干变量。

KMP算法

暴力法的时间复杂度是O(mn),而KMP的时间复杂度是O(m+n),是因为其能在非完全匹配的过程中提取到有效信息进行复用,以减少重复匹配的消耗

暴力法匹配字符串,当出现不同位置时,将原字符串的指针移动至本次起始点的下一个位置,匹配串的指针移动至起始位置。继续尝试匹配,发现对不上,原串的指针会一直往后移动,知道能够与匹配串对上位置。

import java.util.Arrays;

class Solution {
    public int strStr(String haystack, String needle) {

        int haystackLength = haystack.length();
        int needleLen = needle.length();

        if(needleLen > haystackLength){
            return -1;
        }

        char[] haystackArr = haystack.toCharArray();
        char[] needleArr = needle.toCharArray();
        int[] next = new int[needleLen];
        getNext(next, needle.toCharArray());
        int i = 0;
        int j = 0;
        while (i < haystackLength) {
            if (haystackArr[i] != needleArr[j]) {
                while (j != 0 && haystackArr[i] != needleArr[j]) {
                    j = next[j - 1];
                }
                if (j == 0 && haystackArr[i] != needleArr[j]) {
                    i++;
                }
            } else {
                i++;
                j++;
            }

            if (j == needleLen) {
                return i - j;
            }
        }
        return -1;
    }

    private void getNext(int[] next, char[] arr) {
        int len = arr.length;
        int j = 0;
        int i = 1;
        while (i < len) {
            if (arr[i] == arr[j]) {
                next[i] = j + 1;
                i++;
                j++;
            } else {
                while (j > 0 && arr[i] != arr[j]) {
                    j = next[j - 1];
                }
                if (j == 0 && arr[i] != arr[j]) {
                    next[i] = 0;
                    i++;
                }
            }
        }
    }
}

在这里插入图片描述

(*简单 - KMP算法)459. 重复的子字符串

在这里插入图片描述

假设原字符串S是由子串s重复N次而成的,则S+S则有子串s重复2N次,那么现在有S=Ns,S+S=2Ns,其中N>=2。如果条件成立,掐头去尾破坏两个s,S+S中至少还有2(N-1)s,又因为N>=2,因此在S+S的索引从[0,length-2]中必出现一次以上

class Solution {
    public boolean repeatedSubstringPattern(String s) {
        return (s + s).substring(1, (s + s).length() - 1).contains(s);
    }
}

在这里插入图片描述

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

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

相关文章

word怎么转excel?一键转换并不难

在职场中&#xff0c;常常需要将 Word 文档转换为 Excel 表格&#xff0c;以便更好地管理和数据分析。本文将介绍两种 Word 转 Excel 的方法&#xff0c;以及如何在 Excel 中处理转换后的数据。 方法一&#xff1a;使用文本转换向导 使用Word的文本转换向导&#xff0c;将Word文…

第二篇、基于Arduino uno,用oled0.96寸屏幕显示数字和字符——结果导向

0、结果 说明&#xff1a;先来看看实际的结果&#xff0c;如果是你想要的&#xff0c;可以接着往下看。 1、外观 说明&#xff1a;本次使用的oled是0.96寸的&#xff0c;别的规格的屏幕不一定适用本教程&#xff0c;一般而言有显示白色、蓝色和蓝黄一起显示的。 2、连线 说…

SQL执行过程

1. select 语句执行过程 一条 select 语句的执行过程如上图所示 1、建立连接 连接器会校验你输入的用户名和密码是否正确&#xff0c;如果错误会返回提示&#xff0c;如果正确&#xff0c;连接器会查询当前用户对于的权限。连接器的作用就是校验用户权限 2、查询缓存 MySQL…

VPX通信基础理论

新型VPX(VITA 46)标准是自从VME引入后的25年来&#xff0c;对于VME总线架构的最重大也是最重要的改进。它将增加背板带宽&#xff0c;集成更多的I/O&#xff0c;扩展了格式布局。 目前&#xff0c;VME64x已经不能满足国防和航空领域越来越高的性能要求和更为恶劣环境下的应用。…

老杨说运维 | 农商行数字化转型的误区与破局之道

为推动农村中小银行更好地满足人民银行《金融科技发展规划&#xff08;2022—2025年&#xff09;》及银保监会《关于银行业保险业数字化转型的指导意见》对银行数字化转型的相关要求&#xff0c;加快推进农村基层数字化治理&#xff0c;助力乡村振兴&#xff0c;农信银资金清算…

低成本副业:开发小程序商城攻略

随着互联网的普及和电子商务的兴起&#xff0c;越来越多的人选择做点副业&#xff0c;其中开发小程序商城是一个不错的选择。相比传统的实体店&#xff0c;小程序商城的成本更低&#xff0c;而且门槛更低&#xff0c;可以让更多的人参与到副业中来。那么&#xff0c;如何开发自…

SOLIDWORKS 认证考试简介

1、SOLIDWORKS 认证助理工程师-机械设计 (CSWA–Mechanical Design) 证书简介&#xff1a;通过CSWA 认证证明了您在 SOLIDWORKS 上的专长&#xff0c;即表示您已成功展示了使用 SOLIDWORKS 机械设计工具的能力&#xff0c;了解 SOLIDWORKS 中可帮助设计机械零部件的工具集。 考…

大模型时代的BERT 详解

最近在学习BERT。 简单说几句。 BERTBidirectional Encoder Representation from Transformer 作者是谷歌的团队 主要亮点是使用transformer和pre-trainning未标注的数据&#xff0c;训练出来一个通用的语言模型。 0&#xff1a;背景 视觉算法因为有ImageNet的存在&#…

Matlab --- 如何用matlab在三维坐标系中画一个三维向量

用MATLAB画三维向量 前两天&#xff0c;我在写Gram-Schmidt正交化的文章时&#xff0c;想到最好用matlab把还没有经过正交化计算的原始向量&#xff0c;和已经经过正交化处理后的正交基&#xff0c;在三维坐标系中&#xff0c;用图像的方式表示出来。这样可以更加直观的看到向量…

vue3实现动态菜单和动态路由和刷新后白屏处理

前言&#xff1a; 项目中&#xff0c;当每一个角色得到的界面不一致的时候&#xff0c;我们就不能使用静态菜单了&#xff0c;而是要从后端得到动态的菜单数据&#xff0c;然后动态的将菜单数据展示在界面上。 除了在界面展示&#xff0c;也还要将界面的路由动态添加&#xf…

档案管理流程,文件上传,文件解析流程

文件上传 先简单说下文件上传的步骤吧 控制层简单左下转发 PostMapping("uploadAndParsing") public ResponseResult uploadAndParsing(RequestParam("file") MultipartFile file){try {String accessToken Header.getAuthorization(request.getHeader(…

2022年度互联网平均薪资出炉~

近期&#xff0c;国家统计局发布2022年平均工资数据&#xff0c;互联网行业薪资再次成为大家关注的焦点。 在2022年分行业门类分岗位就业人员年平均工资中&#xff0c;信息传输、软件和信息技术服务业的薪资遥遥领先其他行业&#xff0c;为全国平均薪资水平的 1.78 倍&#xf…

H-buildX项目(学习笔记1.0)

记录一下自己的学习过程。 首先&#xff0c;下载H-buildX软件&#xff0c;直接度娘下载即可。 以前一直用的是vscode&#xff0c;这次做网上的项目用到了这个。 打开 就是这样的界面&#xff0c;首先介绍几个常用的功能 右上角的预览&#xff0c;也就是运行你的Vue项目的界面效…

2023华为OD机试(A卷+B卷)(Java C++ Python JS)真题目录 + 考点 + 通过率

文章目录 &#x1f680;前言华为OD刷题列表&#xff0c;每天十题&#xff0c;刷出算法新高度&#xff0c;刷出人生新际遇&#x1f530;刷题列表&#xff1a;华为OD机试真题&#xff08;Java C Python JS&#xff09; &#x1f680;其他华为OD机试题清单 &#x1f4dd;最后作者&…

【最新整理】一起看看86 个 ChatGPT 插件

今天我们来看看这86个插件都是做什么的&#xff1f; Shimmer&#xff1a;跟踪膳食并获得更健康生活方式的见解 World News&#xff1a;总结新闻头条 Bohita&#xff1a;用您能描述的任何图像制作服装 Portfolio Pilot&#xff1a;您的 AI 投资指南&#xff1a;投资组合评估…

跟着我学 AI丨五分钟了解人工智能的发展史

随着 ChatGPT 火出圈&#xff0c;又接二连三出现了文心一言、Midjourney、FireFly 等创新性的 AI 产品&#xff0c;互联网掀起的 AI 风暴已经席卷了全球各个角落。AI 究竟为什么这么强大&#xff1f;从什么时候开始冒出来的呢&#xff1f;今天我就带大家认识一下 AI 的发展史。…

软件设计师考试——面向对象设计模式分类

提示&#xff1a;文章写完后&#xff0c;目录可以自动生成&#xff0c;如何生成可参考右边的帮助文档 文章目录 一、面向对象设计——设计模式的分类一、创建型模式二、结构型模式三、行为型模式 二、历年真题——面向对象设计模式分类2009上半年2009下半年2010上半年2010下半年…

深度学习神经网络学习笔记-多模态方向-12-DBpedia: A Nucleus for a Web of Open Data

摘要 DBpedia是一个社区努力从维基百科中提取结构化信息&#xff0c;并使这些信息在网络上可用。DBpedia允许您对来自维基百科的数据集提出复杂的查询&#xff0c;并将网络上的其他数据集链接到维基百科数据。我们描述了DBpedia数据集的提取&#xff0c;以及产生的信息如何在网…

img标签-访问绝对路径图片出现403的解决办法

img标签-访问绝对路径图片出现403的解决办法 图片请求显示403打不开 403是防止盗链的错误&#xff08;这种设计&#xff0c;是api厂商正常保证自己的服务器不被刷流量&#xff09; 方法一&#xff1a;使用no-referrer 这种方案不仅针对图片的防盗链,还可以是其他标签. 在前端…

「谷云科技」RestCloud新一代(智能)全域数据集成平台发布

5月18日&#xff0c;RestCloud在其成立六周年的当天&#xff0c;发布了“新一代&#xff08;智能&#xff09;全域数据集成平台”。 根据业内专家、学者和从业者通过实践和研究总结&#xff0c;数据集成大体可以分为4个阶段&#xff1a;早期阶段、数据集成软件工具、企业级数据…