java算法day7

2024-04-28 00:04
文章标签 java 算法 day7

本文主要是介绍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);}
}

这篇关于java算法day7的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/941846

相关文章

Java编译生成多个.class文件的原理和作用

《Java编译生成多个.class文件的原理和作用》作为一名经验丰富的开发者,在Java项目中执行编译后,可能会发现一个.java源文件有时会产生多个.class文件,从技术实现层面详细剖析这一现象... 目录一、内部类机制与.class文件生成成员内部类(常规内部类)局部内部类(方法内部类)匿名内部类二、

SpringBoot实现数据库读写分离的3种方法小结

《SpringBoot实现数据库读写分离的3种方法小结》为了提高系统的读写性能和可用性,读写分离是一种经典的数据库架构模式,在SpringBoot应用中,有多种方式可以实现数据库读写分离,本文将介绍三... 目录一、数据库读写分离概述二、方案一:基于AbstractRoutingDataSource实现动态

Springboot @Autowired和@Resource的区别解析

《Springboot@Autowired和@Resource的区别解析》@Resource是JDK提供的注解,只是Spring在实现上提供了这个注解的功能支持,本文给大家介绍Springboot@... 目录【一】定义【1】@Autowired【2】@Resource【二】区别【1】包含的属性不同【2】@

springboot循环依赖问题案例代码及解决办法

《springboot循环依赖问题案例代码及解决办法》在SpringBoot中,如果两个或多个Bean之间存在循环依赖(即BeanA依赖BeanB,而BeanB又依赖BeanA),会导致Spring的... 目录1. 什么是循环依赖?2. 循环依赖的场景案例3. 解决循环依赖的常见方法方法 1:使用 @La

Java枚举类实现Key-Value映射的多种实现方式

《Java枚举类实现Key-Value映射的多种实现方式》在Java开发中,枚举(Enum)是一种特殊的类,本文将详细介绍Java枚举类实现key-value映射的多种方式,有需要的小伙伴可以根据需要... 目录前言一、基础实现方式1.1 为枚举添加属性和构造方法二、http://www.cppcns.co

Elasticsearch 在 Java 中的使用教程

《Elasticsearch在Java中的使用教程》Elasticsearch是一个分布式搜索和分析引擎,基于ApacheLucene构建,能够实现实时数据的存储、搜索、和分析,它广泛应用于全文... 目录1. Elasticsearch 简介2. 环境准备2.1 安装 Elasticsearch2.2 J

Java中的String.valueOf()和toString()方法区别小结

《Java中的String.valueOf()和toString()方法区别小结》字符串操作是开发者日常编程任务中不可或缺的一部分,转换为字符串是一种常见需求,其中最常见的就是String.value... 目录String.valueOf()方法方法定义方法实现使用示例使用场景toString()方法方法

Java中List的contains()方法的使用小结

《Java中List的contains()方法的使用小结》List的contains()方法用于检查列表中是否包含指定的元素,借助equals()方法进行判断,下面就来介绍Java中List的c... 目录详细展开1. 方法签名2. 工作原理3. 使用示例4. 注意事项总结结论:List 的 contain

Java实现文件图片的预览和下载功能

《Java实现文件图片的预览和下载功能》这篇文章主要为大家详细介绍了如何使用Java实现文件图片的预览和下载功能,文中的示例代码讲解详细,感兴趣的小伙伴可以跟随小编一起学习一下... Java实现文件(图片)的预览和下载 @ApiOperation("访问文件") @GetMapping("

Spring Boot + MyBatis Plus 高效开发实战从入门到进阶优化(推荐)

《SpringBoot+MyBatisPlus高效开发实战从入门到进阶优化(推荐)》本文将详细介绍SpringBoot+MyBatisPlus的完整开发流程,并深入剖析分页查询、批量操作、动... 目录Spring Boot + MyBATis Plus 高效开发实战:从入门到进阶优化1. MyBatis