java算法day7

字符串篇

  • java该学的字符串基础
  • 反转字符串
  • 反转字符串Ⅱ
  • 替换数字

java该学的字符串基础。

在Java中,String 类是用来操作字符序列的。Java中的字符串是不可变的,这意味着一旦一个字符串被创建,其内容就不能改变。下面是一些关于Java字符串及其在算法题中常用技巧的详细介绍:

Java中的String类基础
创建字符串:
直接使用双引号:String s = “Hello”;
使用构造函数:String s = new String(“Hello”);

字符串常用方法:
.length() - 返回字符串的长度。
.charAt(index) - 返回指定位置的字符。
.substring(beginIndex, endIndex) - 返回子字符串。
.contains(CharSequence s) - 检查字符串是否包含序列s。
.equals(Object another) - 比较两个字符串的内容是否相等。
.equalsIgnoreCase(String another) - 同上,但忽略大小写。
.split(String regex) - 根据匹配给定的正则表达式来拆分字符串。
.indexOf(String str) - 返回指定子字符串在此字符串中第一次出现处的索引。
.toLowerCase() 和 .toUpperCase() - 转换字符串的大小写。
.trim() - 返回去除前导和尾随空格的字符串副本。

字符串比较:
使用 equals() 方法比较字符串内容,而不是使用 ==,后者比较的是引用。

一个习惯性操作:
想像c++一样,如果String能够按下标访问,修改,那很多题做起来就方便的多。但是上面String由于不可变性。所以它的任何操作并不能够修改字符串的本身。

接下来将解决这个难题。

方法1:转换为字符数组,完成操作后再转为字符串。
看一个例子就懂了。

String s = "Hello";
char[] charArray = s.toCharArray();  //通过toCharArray()方法转换
charArray[1] = 'a';  // 修改第二个字符。变成数组了就可以修改了
String newString = new String(charArray); //创建字符串可以将字符数组传入作为参数。
System.out.println(newString);  // 输出 "Hallo"

方法2:使用StringBuffer或者StringBuilder。

StringBuilder

StringBuilder 是一个可变的字符序列。与不可变的 String 类不同,StringBuilder 允许你在原地修改字符串而不需要每次修改都生成新的字符串对象,这样可以大大提高效率。

StringBuilder是一个非线程安全的可变字符序列,它通常比StringBuffer更快,因为它不进行同步。

创建 StringBuilder 对象
你可以通过多种方式创建 StringBuilder 对象:

StringBuilder sb1 = new StringBuilder();  // 创建一个空的StringBuilder
StringBuilder sb2 = new StringBuilder(10);  // 指定初始容量
StringBuilder sb3 = new StringBuilder("Hello");  // 从一个字符串开始

常用方法

append() - 添加文本到当前StringBuilder对象的末尾。

StringBuilder sb = new StringBuilder("Hello");
sb.append(" World");
System.out.println(sb.toString());  // 输出 "Hello World"

insert() - 在指定位置插入文本

StringBuilder sb = new StringBuilder("Hello World");
sb.insert(6, "Java ");
System.out.println(sb.toString());  // 输出 "Hello Java World"

replace() - 替换StringBuilder中的一部分内容。

StringBuilder sb = new StringBuilder("Hello World");
sb.replace(6, 11, "Java");
System.out.println(sb.toString());  // 输出 "Hello Java"

delete() 和 deleteCharAt() - 删除StringBuilder中的一部分内容或特定位置的字符。

StringBuilder sb = new StringBuilder("Hello World");
sb.delete(5, 11);
System.out.println(sb.toString());  // 输出 "Hello"
sb.deleteCharAt(4);
System.out.println(sb.toString());  // 输出 "Hell"

reverse() - 将StringBuilder中的内容反转。

StringBuilder sb = new StringBuilder("Hello");
sb.reverse();
System.out.println(sb.toString());  // 输出 "olleH"

setCharAt() - 设置指定位置的字符。

StringBuilder sb = new StringBuilder("Hello");
sb.setCharAt(1, 'a');
System.out.println(sb.toString());  // 输出 "Hallo"

length(), capacity() - 获取长度和容量。

StringBuilder sb = new StringBuilder("Hello");
System.out.println("Length: " + sb.length());  // 输出 "Length: 5"
System.out.println("Capacity: " + sb.capacity());  // 输出 "Capacity: 21" (初始容量是16加上字符串长度)

最重要的就是这个sb.toString()转String类型。

使用 StringBuilder 的一个主要优点是它可以避免创建多个临时不可变字符串对象,这在循环或频繁操作字符串内容的场景中非常有用。例如,拼接字符串时,使用 StringBuilder 要比使用 String 直接拼接(使用 + 操作符)效率高得多。

StringBuffer

这两个方法都是类似的,主要区别就在于线程安全性。StringBuffer是线程安全的,而StringBuilder不是线程安全的。这意味着StringBuffer适用于多线程环境中,而StringBuilder则适用于单线程或不需要考虑线程安全的情况。

StringBuffer是一个线程安全的可变字符序列。它通过内部同步来确保多个线程可以安全地同时修改字符串缓冲区。

StringBuffer:在你需要确保字符串操作的线程安全时使用StringBuffer。例如,在web应用服务器或任何多线程应用程序中处理字符串时。
StringBuilder:在单线程环境中或不关心线程安全的情况下使用StringBuilder,因为它没有同步开销,通常会比StringBuffer更快。

总的来说,选择StringBuffer还是StringBuilder主要取决于是否需要线程安全。在性能敏感的应用中,通常推荐使用StringBuilder,除非你需要在多线程环境中操作字符串。

二者都会自动扩容

StringBuffer和StringBuilder都会在需要时自动扩容。这是通过内部机制实现的,以便这两种类型的对象可以在运行时根据需要增加存储容量,以容纳更多的字符。

扩容机制
当你向StringBuffer或StringBuilder添加内容,而当前容量不足以容纳新增的内容时,它们会自动进行扩容。扩容的过程通常涉及以下步骤:

计算新容量:新的容量通常是当前容量的两倍加上2,但这可能因JVM的实现而异。如果这个新计算的容量还不足以容纳新增的数据,那么容量会增加到必要的大小以适应新增的数据。

分配新数组:一旦计算出新的容量,就会创建一个新的字符数组,其大小等于新的容量。

复制数据:原有数组中的数据会被复制到新的数组中。

替换数组:旧的字符数组被新的字符数组替换,旧的数组将被垃圾回收。


反转字符串

这题无论是双指针往中间靠,还是凭借下标的关系都可以完成这个题。

class Solution {
    public void reverseString(char[] s) {
        for(int i = 0;i<s.length/2;i++){ //只到中间
            char temp; //相对的元素进行两两交换。
            temp = s[s.length-i-1];
            s[s.length-i-1] = s[i];
            s[i] = temp;
        }
    }
}

翻转字符串Ⅱ

也很简单,主要就是想清楚2k个元素之中的下标位置。在处理好区间的基础上。对每个区间完成翻转字符串即可。

class Solution {
    public String reverseStr(String s, int k) {
        char[] str = s.toCharArray(); //先转为字符数组
        for(int i = 0;i<str.length;){ //这里就没必要对i进行操作了。处理完一个区间后。i直接跳转到下一个区间的起点就可以了。一旦跳转到下一个区间起点不符合i的限制,循环会自动停止的。
            if(i+2*k-1<=str.length-1){ //当第2k个元素还在字符数组的有效范围。由于下标从0开始,所以第2k个字符的位置在i+2*k-1这个位置。接下来进行翻转数组的操作。
                //翻转前k个字符
                int start=i;
                int end = i+k-1;
                int goNext = i+2*k; //设置i下一个区间的跳转点。
                while(start<=end){ //纯纯双指针交换首尾
                    char temp =str[end];
                    str[end] = str[start];
                    str[start] = temp;
                    start++;
                    end--;
                }
                i = goNext; //i进行跳转
            }else{ 
                //这个时候第2k个元素的下标已经超了,检查里面的字符是在1k以上还是1k以下
                if(i+k-1>=str.length-1){ //检查1k这个地方还在有效范围没有,如果1k这个地方也超了,说明剩余不足1k,全部翻转
                    int start = i;
                    int end = str.length-1;
                    while(start<=end){
                        char temp = str[end];
                        str[end] = str[start];
                        str[start] = temp;
                        start++;
                        end--;
                    }
                    break; //翻转完就可以结束了。因为这种情况只在尾部。
                }else{
                    //1k这个地方如果还在有效区间,那就翻转前k。
                    int start = i;
                    int end = i+k-1;
                    while(start<=end){
                        char temp = str[start];
                        str[start] = str[end];
                        str[end] = temp;
                        start++;
                        end--;
                    }
                    break;//翻转完就可以结束了。因为这种情况只在尾部。
                }
            }
        }
        

        return new String(str); //转为字符串返回
    }
}

替换数字

题目的意思就每遇到一个数字就改为把这个数字去掉,然后插一个字符串"number"进去。java做这个我感觉最好用的办法就是空间换时间了。用StringBuilder。

思路:遍历字符串,是数字就把number字符串插入,不是数字就把遍历的字符给插入。
我的写法:看着就是有点长了。

import java.util.Scanner;

class Main{
    public static void main(String[] args){
        Scanner scanner = new Scanner(System.in);
        String s = scanner.nextLine();
        String result = replaceNum(s);
        System.out.println(result);
        
    }
    
    
    
    public static String replaceNum(String s){
        int count = 0;
        char[] str = s.toCharArray();
        for(char c : str){
            if(c>='0' && c <='9'){
                count++;
            }
        }
        String insertStr = "number";
        int numLength = 6;
        int sum = s.length() - count + numLength*count;
        StringBuilder sb = new StringBuilder(sum);
        for(char c:str){
            if(c>='0'&& c<='9'){
                sb.append(insertStr);
            }else{
                sb.append(c);
            }
        }
        
        return sb.toString();
        
    }
    
}

代码随想录解法:
这个解法简短就在于直接用s.charAt()访问字符串。而我是转字符数组多此一举。

所以以后如果是这种遍历插入构造新字符串的。不涉及修改元素组来进行操作,最好还是用charAt(),如果是原数组进行处理,那么转为字符数组要好做的多。

import java.util.Scanner;

class Main {
    public static void main(String[] args) {
        Scanner in = new Scanner(System.in);
        String s = in.nextLine();
        StringBuilder sb = new StringBuilder();
        for (int i = 0; i < s.length(); i++) {
            if (Character.isDigit(s.charAt(i))) {
                sb.append("number");
            }else sb.append(s.charAt(i));
        }
        System.out.println(sb);
    }
}

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

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

相关文章

《数字化决策》第三版的启示

目录 一、《数字化决策》读后感 二、《数字化决策》给人的启示 三、思考题 一、《数字化决策》读后感 随着科技的飞速发展&#xff0c;数字化已经成为商业领域的核心力量。在这样的背景下&#xff0c;《数字化决策》第三版为我们提供了宝贵的认知提升&#xff0c;帮助我们更…

不同路径 1 2

class Solution {public int uniquePaths(int m, int n) {int[][] dpnew int[m][n];//记录到每个格子有多少种路径for(int i0;i<m;i) dp[i][0]1;for(int j0;j<n;j) dp[0][j]1;//初始化for(int i1;i<m;i){for(int j1;j<n;j){dp[i][j]dp[i-1][j]dp[i][j-1];}}return …

实习算法准备之BFSDFS

这里写目录标题 1 理论1.1 BFS框架 2 例题2.1 二叉树的最小高度2.2 打开转盘锁2.3 滑动谜题 1 理论 BFS和DFS是两个遍历算法&#xff0c;其中DFS之前已经接触过&#xff0c;就是回溯&#xff0c;忘记的话请回顾回溯篇的例题&#xff08;全排列&#xff0c;N皇后&#xff09; B…

C++解方程组的库

解决多元多次方程组的问题&#xff0c;你可以考虑以下几个C库&#xff1a; Eigen: Eigen库是一个高性能的C模板库&#xff0c;用于线性代数运算。它提供了强大的矩阵运算功能&#xff0c;可以用来解多元一次方程组。对于多次方程组&#xff0c;你可能需要结合Eigen和一些数值优…

Rust网络请求神器reqwest介绍和使用,5分钟速学

在 Rust 生态中&#xff0c;reqwest 可以说是最流行的 HTTP 客户端库了。它提供了一个高层级的、人性化的 API&#xff0c;让我们可以非常轻松地发送各种 HTTP 请求和处理响应。无论是 quickstart、自定义请求头、cookie 管理&#xff0c;还是文件上传&#xff0c;reqwest 都能…

了解Cookie登录:原理、实践与安全指南

什么是Cookie登录&#xff1f; Cookie是什么 当你首次登录网站时&#xff0c;你会输入用户名和密码。在后台&#xff0c;网站的服务器验证这些凭据是否正确。一旦确认你的身份无误&#xff0c;服务器就会创建一个Cookie&#xff0c;并将其发送到你的浏览器。这了解Cookie登录…

38-数组 _ 一维数组

38-1 数组的创建 数组是一组相同类型元素的集合。 数组的创建方式&#xff1a; type_t arr_name [const_n]; //type_t 是指数组的元素类型 //const_n是一个常量表达式&#xff0c;用来指定数组的大小 举例&#xff1a; int arr[10]; char ch[5]; double data[20]; 问&…

HarmonyOS 实战开发-MindSpore Lite引擎进行模型推理

场景介绍 MindSpore Lite 是一款 AI 引擎&#xff0c;它提供了面向不同硬件设备 AI 模型推理的功能&#xff0c;目前已经在图像分类、目标识别、人脸识别、文字识别等应用中广泛使用。 本文介绍使用 MindSpore Lite 推理引擎进行模型推理的通用开发流程。 基本概念 在进行开…

vscode连接远程Linux服务器时,没有权限新建文件夹或者文件

参考链接&#xff1a; VS code 保存或新建文件没有权限的问题 vscode连接远程Linux服务器时&#xff0c;没有权限新建文件夹或者文件&#xff1a; 用一条命令解决&#xff1a; sudo chown -R myuser /path/to/foldermyuser是当前用户名&#xff0c; /path/to/folder是 需要操…

编程学习路线

Java最强学习路线 快来官网定制一套属于自己的学习路线吧 官方网址&#xff1a; Learn to become a modern Java developerCommunity driven, articles, resources, guides, interview questions, quizzes for java development. Learn to become a modern Java developer by…

运维笔记:基于阿里云跨地域服务器通信(上)

运维笔记 阿里云&#xff1a;跨地域服务器通信&#xff08;上&#xff09; - 文章信息 - Author: 李俊才 (jcLee95) Visit me at CSDN: https://jclee95.blog.csdn.netMy WebSite&#xff1a;http://thispage.tech/Email: 291148484163.com. Shenzhen ChinaAddress of this a…

【嵌入式AI开发】轻量级卷积神经网络MobileNet项目实战——文末完整源码工程文件

前言:本文介绍轻量级卷积神经网络MobileNet网络实战,包含MobileNetV1、MobileNetV2、ResNet50三个预训练模型可供选择。 实现:1.预训练MobileNet图像分类,2.调用摄像头实时MobileNet图像分类,3.MobileNet视频图像分类。 MobileNet网络理论详解:【嵌入式AI开发】轻量级卷…

git提交常用

git config --global user.name "你的名字或昵称" git config --global user.email "你的邮箱" 第一次上传到码云 1.找到要提交到码云的文件夹 右击打开Git Bash Here 2.用命令行创建本地仓库 git init 3.将待全部文件放入缓冲区 git add . 4.提交缓…

优化贪吃蛇在前进过程中,前进和后退的问题

1. 左边为head,右边为tail 定义相反数在abs&#xff08;&#xff09;绝对值函数中实现 2. 在转向函数turn()中&#xff0c;如果绝对值不相等的时候才赋予方向的值 3.贪吃蛇吃食物的思路 3.1 初始化食物initFood(), 蛇碰到食物函数hasFood&#xff08;&#xff09;,在移…

如何用Python实现智能客服问答系统

随着人工智能技术的不断发展&#xff0c;机器人客服与聊天系统成为了热门话题。Python作为一种简单易学、功能强大的编程语言&#xff0c;在机器人客服与聊天系统的开发中具有广泛应用。 本文将介绍如何使用Python实现机器人客服与聊天系统&#xff0c;包括实现方式、代码示例和…

Mysql-主从复制理解

环境&#xff1a;mysql&#xff0c;主从复制&#xff0c;必须有2个mysql实例&#xff0c;也就是说可以在一台电脑上安装2个msyql&#xff0c;或者2台服务器&#xff0c;一个主服务器&#xff0c;一个从服务器 在实际的生产中&#xff0c;为了解决Mysql的单点故障已经提高MySQL的…

【Unity动画系统】动画基本原理与Avater骨骼复用

动画基本原理 动画片段文件是一个描述物体变化状态的文本文件 在Unity中创建的资源文件大多都是YAML语言编写的文本文件 Curves表示一种变化状态&#xff0c;为空的话则没有记录任何内容 位置变化后的旋转变化状态&#xff1a; 动画文件里的Path名字要相同才能播放相同的动画 …

外贸财务挑战面面观:应对难题之道大揭秘!

出海也开始卷起来了。越来越多的中国企业投身海外市场&#xff0c;寻求更广阔的发展空间。然而&#xff0c;出海之路并非坦途&#xff0c;企业既需把握全球商机&#xff0c;又需应对数字化转型、本土化运营、文化差异性等多重挑战。企业出海&#xff0c;该如何应对这些风浪&…

GPU服务器和普通服务器有何区别?

众所周知&#xff0c;服务器是网络中的重要设备&#xff0c;要接受少至几十人、多至成千上万人的访问&#xff0c;因此对服务器具有大数据量的快速吞吐、超强的稳定性、长时间运行等严格要求。 GPU服务器和普通服务器的主要区别在于硬件配置和适用场景&#xff0c;特别是处理器…

C 函数递归

目录 什么是递归 递归的限制条件 递归的例子 1、用递归求n的阶乘 递归扩展学习 1、青蛙跳台阶 思路 代码实现 2、汉诺塔问题​ 思路 代码实现 总结 什么是递归 递归&#xff1a;“递推” “回归” 在C语言中&#xff0c;函数递归就是&#xff1a;函数自己调用自…