LeetCode算法成长之路Java字符串相关类总结与经典题目分析

Posted 小新要变强

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了LeetCode算法成长之路Java字符串相关类总结与经典题目分析相关的知识,希望对你有一定的参考价值。

前言

本文小新为大家带来 Java字符串相关类总结与经典题目分析 相关知识,具体内容包括不可变字符序列String介绍(包括:String 的特性String 的构造器String 与其他结构间的转换String 的基本常用方法String 的查找方法String 的字符串截取方法String 的和字符/字符数组相关方法String 的开头与结尾判断方法String 的替换方法),可变字符序列StringBuffer与StringBuilder(包括:StringBuffer 与 StringBuilder 的理解StringBuilder、StringBuffer 的 API),字符串操作经典算法题目(包括:去除字符串两端的空格将字符串进行反转一个字符串在另一个字符串中出现的次数两个字符串中的最大相同子串对字符串中字符进行自然顺序排序)等进行详尽介绍~

不积跬步,无以至千里;不积小流,无以成江海。每天进步一点点,在成为强者的路上,小新与大家共同成长!

📌博主主页:小新要变强 的主页
👉Java全栈学习路线可参考:【Java全栈学习路线】最全的Java学习路线及知识清单,Java自学方向指引,内含最全Java全栈学习技术清单~
👉算法刷题路线可参考:算法刷题路线总结与相关资料分享,内含最详尽的算法刷题路线指南及相关资料分享~
👉Java微服务开源项目可参考:企业级Java微服务开源项目(开源框架,用于学习、毕设、公司项目、私活等,减少开发工作,让您只关注业务!)


目录

Java字符串相关类总结与经典题目分析

在LeetCode算法题目中有许多 关于字符串的题目,对于这些题目,如果我们需要熟练掌握Java中的字符串类,包括其中常用的方法,对于这类题目就可以游刃有余。

下面会先为大家对不可变字符序列String,及可变字符序列StringBuffer与StringBuilder进行介绍,并为大家总结有关的常用方法,最后为大家展示几道与字符串有关的经典算法题目。

一、不可变字符序列String

1️⃣String 的特性

  • java.lang.String 类代表字符串。Java 程序中所有的字符串文字(例如 “hello” )都可以看作是实现此类的实例。
  • 字符串是常量,用双引号引起来表示。它们的值在创建之后不能更改。
  • 字符串 String 类型本身是 final 声明的,意味着我们不能继承String。
  • String 对象的字符内容是存储在一个字符数组 value[]中的。“abc” 等效于 char[] data=‘h’,‘e’,‘l’,‘l’,‘o’。

  • Java 语言提供对字符串串联符号(“+”)以及将其他对象转换为字符串的特殊支持(toString()方法)。

2️⃣String 的构造器

  • public String() :初始化新创建的 String 对象,以使其表示空字符序列。
  • String(String original): 初始化一个新创建的 String 对象,使其表示一个与参数相同的字符序列;换句话说,新创建的字符串是该参数字符串的副本。
  • public String(char[] value) :通过当前参数中的字符数组来构造新的String。
  • public String(char[] value,int offset, int count) :通过字符数组的 一部分来构造新的String。
  • public String(byte[] bytes) :通过使用平台的默认字符集解码当前参数中的字节数组来构造新的 String。
  • public String(byte[] bytes,String charsetName) :通过使用指定的字符集解码当前参数中的字节数组来构造新的 String。

3️⃣String 与其他结构间的转换

🍀字符串 --> 基本数据类型、包装类

  • Integer 包装类的 public static int parseInt(String s):可以将由“数字”字符组成的字符串转换为整型。
  • 类似地,使用 java.lang 包中的 Byte、Short、Long、Float、Double类调相应的类方法可以将由“数字”字符组成的字符串,转化为相应的基本数据类型。

🍀基本数据类型、包装类 --> 字符串

  • 调用 String 类的 public String valueOf(int n)可将 int 型转换为字符串。
  • 相应的 valueOf(byte b)、valueOf(long l)、valueOf(float f)、valueOf(double d)、valueOf(boolean b)可由参数的相应类型到字符串的转换。

🍀字符数组 --> 字符串

  • String 类的构造器:String(char[]) 和 String(char[],int offset,int length)
    分别用字符数组中的全部字符和部分字符创建字符串对象。

🍀字符串 --> 字符数组

  • public char[] toCharArray():将字符串中的全部字符存放在一个字符数组中的方法。
  • public void getChars(int srcBegin, int srcEnd, char[] dst, int dstBegin):提供了将指定索引范围内的字符串存放到数组中的方法。

🍀字符串 --> 字节数组(编码)

  • public byte[] getBytes() :使用平台的默认字符集将此 String 编码为 byte序列,并将结果存储到一个新的 byte 数组中。
  • public byte[] getBytes(String charsetName) :使用指定的字符集将此String编码到byte 序列,并将结果存储到新的 byte 数组。

🍀字节数组 --> 字符串(解码)

  • String(byte[]):通过使用平台的默认字符集解码指定的 byte 数组,构造一个新的String。
  • String(byte[],int offset,int length) :用指定的字节数组的一部分,即从数组起始位置 offset开始取 length 个字节构造一个字符串对象。
  • String(byte[], String charsetName ) 或 new String(byte[], int, int,String charsetName ):解码,按照指定的编码方式进行解码。

4️⃣String 的基本常用方法

String 类包括的方法可用于检查序列的单个字符、比较字符串、搜索字符串、提取子字符串、创建字符串副本并将所有字符全部转换为大写或小写。

  • (1)boolean isEmpty():字符串是否为空
  • (2)int length():返回字符串的长度
  • (3)String concat(xx):拼接
  • (4)boolean equals(Object obj):比较字符串是否相等,区分大小写
  • (5)boolean equalsIgnoreCase(Object obj):比较字符串是否相等,不区分大小写
  • (6)int compareTo(String other):比较字符串大小,区分大小写,按照 Unicode 编码值比较大小
  • (7)int compareToIgnoreCase(String other):比较字符串大小,不区分大小写
  • (8)String toLowerCase():将字符串中大写字母转为小写
  • (9)String toUpperCase():将字符串中小写字母转为大写
  • (10)String trim():去掉字符串前后空白符
  • (11)public String intern():结果在常量池中共享

5️⃣String 的查找方法

  • (1)boolean contains(xx):是否包含 xx
  • (2)int indexOf(xx):从前往后找当前字符串中 xx,即如果有返回第一次出现的下标,要是没有返回-1
  • (3)int indexOf(String str, int fromIndex):返回指定子字符串在此字符串中第一次出现处的索引,从指定的索引开始
  • (4)int lastIndexOf(xx):从后往前找当前字符串中 xx,即如果有返回最后一次出现的下标,要是没有返回-1
  • (5)int lastIndexOf(String str, int fromIndex):返回指定子字符串在此字符串中最后一次出现处的索引,从指定的索引开始反向搜索。

6️⃣String 的字符串截取方法

  • (1)String substring(int beginIndex) :返回一个新的字符串,它是此字符串的从 beginIndex开始截取到最后的一个子字符串。
  • (2)String substring(int beginIndex, int endIndex) :返回一个新字符串,它是此字符串从beginIndex开始截取到 endIndex(不包含)的一个子字符串。

7️⃣String 的和字符/字符数组相关方法

  • (1)char charAt(index):返回[index]位置的字符。
  • (2)char[] toCharArray(): 将此字符串转换为一个新的字符数组返回 。
  • (3)static String valueOf(char[] data) :返回指定数组中表示该字符序列的 String 。
  • (4)static String valueOf(char[] data, int offset, int count) :返回指定数组中表示该字符序列的 String 。
  • (5)static String copyValueOf(char[] data): 返回指定数组中表示该字符序列的 String 。
  • (6)static String copyValueOf(char[] data, int offset, int count):返回指定数组中表示该字符序列的 String。

8️⃣String 的开头与结尾判断方法

  • (1)boolean startsWith(xx):测试此字符串是否以指定的前缀开始 。
  • (2)boolean startsWith(String prefix, int toffset):测试此字符串从指定索引开始的子字符串是否以指定前缀开始。
  • (3)boolean endsWith(xx):测试此字符串是否以指定的后缀结束。

9️⃣String 的替换方法

  • (1)String replace(char oldChar, char newChar):返回一个新的字符串,它是通过用 newChar替换此字符串中出现的所有 oldChar 得到的。 不支持正则。
  • (2)String replace(CharSequence target, CharSequence replacement): 使用指定的字面值替换序列替换此字符串所有匹配字面值目标序列的子字符串。
  • (3)String replaceAll(String regex, String replacement):使用给定的replacement 替换此字符串所有匹配给定的正则表达式的子字符串。
  • (4)String replaceFirst(String regex, String replacement):使用给定的replacement 替换此字符串匹配给定的正则表达式的第一个子字符串。

二、可变字符序列StringBuffer与StringBuilder

因为 String 对象是不可变对象,虽然可以共享常量对象,但是对于频繁字符串的修改和拼接操作,效率极低,空间消耗也比较高。因此,JDK 又在java.lang包提供了可变字符序列 StringBuffer 和 StringBuilder 类型。

1️⃣StringBuffer 与 StringBuilder 的理解

  • java.lang.StringBuffer 代表可变的字符序列,JDK1.0中声明,可以对字符串内容进行增删,此时不会产生新的对象。比如:
//情况 1:
String s = new String("我喜欢学习");
//情况 2:
StringBuffer buffer = new StringBuffer("我喜欢学习");
buffer.append("数学");

  • StringBuilder 和 StringBuffer 非常类似,均代表可变的字符序列,而且提供相关功能 的方法也一样。
  • 区分 String、StringBuffer、StringBuilder:
  • String:不可变的字符序列; 底层使用 char[]数组存储(JDK8.0 中)
  • StringBuffer:可变的字符序列;线程安全(方法有 synchronized 修饰),效率低;底层使用 char[]数组存储 (JDK8.0 中)
  • StringBuilder:可变的字符序列; jdk1.5 引入,线程不安全的,效率高;底 层使用 char[]数组存储(JDK8.0中)

2️⃣StringBuilder、StringBuffer 的 API

StringBuilder、StringBuffer 的 API 是完全一致的,并且很多方法与 String 相同。

🍀常用 API

  • (1)StringBuffer append(xx):提供了很多的 append()方法,用于进行字符串追加的方式拼接
  • (2)StringBuffer delete(int start, int end):删除[start,end)之间字符
  • (3)StringBuffer deleteCharAt(int index):删除[index]位置字符
  • (4)StringBuffer replace(int start, int end, String str):替换[start,end)范围的字符序列为 str
  • (5)void setCharAt(int index, char c):替换[index]位置字符
  • (6)char charAt(int index):查找指定 index 位置上的字符
  • (7)StringBuffer insert(int index, xx):在[index]位置插入 xx
  • (8)int length():返回存储的字符数据的长度
  • (9)StringBuffer reverse():反转

🍀与 String相同的方法

  • (1)int indexOf(String str):在当前字符序列中查询 str 的第一次出现下标
  • (2)int indexOf(String str, int fromIndex):在当前字符序列[fromIndex,最后]中查询str 的第一次出现下标
  • (3)int lastIndexOf(String str):在当前字符序列中查询 str 的最后一次出现下标
  • (4)int lastIndexOf(String str, int fromIndex):在当前字符序列[fromIndex,最后]中查询 str 的最后一次出现下标
  • (5)String substring(int start):截取当前字符序列[start,最后]
  • (6)String substring(int start, int end):截取当前字符序列[start,end)
  • (7)String toString():返回此序列中数据的字符串表示形式
  • (8)void setLength(int newLength) :设置当前字符序列长度为newLength

三、字符串操作经典算法题目

1️⃣题目1:去除字符串两端的空格

模拟一个 trim 方法,去除字符串两端的空格。

public String myTrim(String str) 
  if (str != null) 
    int start = 0;// 用于记录从前往后首次索引位置不是空格的位置的索引
    int end = str.length() - 1;// 用于记录从后往前首次索引位置不是空格的位置的索引
    while (start < end && str.charAt(start) == ' ') 
      start++;
    
    while (start < end && str.charAt(end) == ' ') 
      end--;
    
    if (str.charAt(start) == ' ') 
      return "";
    
    return str.substring(start, end + 1);
  
  return null;


@Test
public void testMyTrim() 
  String str = " a ";
  // str = " ";
  String newStr = myTrim(str);
  System.out.println("---" + newStr + "---");

2️⃣题目2:将字符串进行反转

将一个字符串进行反转。将字符串中指定部分进行反转。比如“abcdefg”反转为”abfedcg”。

// 方式一:
public String reverse1(String str, int start, int end) // start:2,end:5
  if (str != null) 
  // 1.
  char[] charArray = str.toCharArray();
  // 2.
  for (int i = start, j = end; i < j; i++, j--) 
    char temp = charArray[i];
    charArray[i] = charArray[j];
    charArray[j] = temp;
  
  // 3.
  return new String(charArray);
  
  return null;


// 方式二:
public String reverse2(String str, int start, int end) 
  // 1.
  String newStr = str.substring(0, start);// ab
  // 2.
  for (int i = end; i >= start; i--) 
    newStr += str.charAt(i);
   // abfedc
  // 3.
  newStr += str.substring(end + 1);
  return newStr;


// 方式三:推荐 (相较于方式二做的改进)
public String reverse3(String str, int start, int end) // ArrayLi
  st list = new ArrayList(80);
  // 1.
  StringBuffer s = new StringBuffer(str.length());
  // 2.
  s.append(str.substring(0, start));// ab
  // 3.
  for (int i = end; i >= start; i--) 
    s.append(str.charAt(i));
  
  // 4.
  s.append(str.substring(end + 1));
  // 5.
  return s.toString();


@Test
public void testReverse() 
  String str = "abcdefg";
  String str1 = reverse3(str, 2, 5);
  System.out.println(str1);// abfedcg

3️⃣题目3:一个字符串在另一个字符串中出现的次数

获取一个字符串在另一个字符串中出现的次数。 比如:获取“ ab”在“abkkcadkabkebfkabkskab” 中出现的次数。

// 判断 str2 在 str1 中出现的次数
public int getCount(String mainStr, String subStr) 
  if (mainStr.length() >= subStr.length()) 
    int count = 0;
    int index = 0;
    // while((index = mainStr.indexOf(subStr)) != -1)
    //   count++;
    //   mainStr = mainStr.substring(index + subStr.length());
    // 
    // 改进:
    while ((index = mainStr.indexOf(subStr, index)) != -1) 
      index += subStr.length();
      count++;
    
    return count;
   else 
    return 0;
  


@Test
public void testGetCount() 
  String str1 = "cdabkkcadkabkebfkabkskab";
  String str2 = "ab";
  int count = getCount(str1, str2);
  System.out.println(count);

4️⃣题目4:两个字符串中的最大相同子串

获取两个字符串中最大相同子串。比如: str1 = "abcwerthelloyuiodef“; str2 = “cvhellobnm” 提示:将短的那个串进行长度依次递减的子串与较长的串比较。

// 如果只存在一个最大长度的相同子串
public String getMaxSameSubString(String str1, String str2) 
  if (str1 != null && str2 != null) 
    String maxStr = (str1.length() > str2.length()) ? str1 : str2;
    String minStr = (str1.length() > str2.length()) ? str2 : str1;
    int len = minStr.length();
    for (int i = 0; i < len; i++) // 0 1 2 3 4 此层循环决定要去几个字符
      for (int x = 0, y = len - i; y <= len; x++, y++) 
        if (maxStr.contains(minStr.substring(x, y))) 
          return minStr.substring(x, y);
        
      
    
  
  return null;


// 如果存在多个长度相同的最大相同子串
// 此时先返回 String[],后面可以用集合中的 ArrayList 替换,较方便
public String[] getMaxSameSubString1(String str1, String str2) 
  if (str1 != null && str2 != null) 
    StringBuffer sBuffer = new StringBuffer();
    String maxString = (str1.length() > str2.length()) ? str1 : str2;
    String minString = (str1.length() > str2.length()) ? str2 : str1;
    int len = minString.length();
    for (int i = 0; i < len; i++) 
      for (int x = 0, y = len - i; y <= len; x++, y++) 
        String subString = minString.substring(x, y);
        if (maxString.contains(subString)) 
          sBuffer.append(subString + ",");
        
      
      System.out.println(sBuffer);
      if (sBuffer.length() != 0) 
        break;
      
    
    String[] split = sBuffer.toString().replaceAll(",$", "").split("\\\\,");
    return split;
  
  return null;


// 如果存在多个长度相同的最大相同子串:使用 ArrayList
// public List<String> getMaxSameSubString1(String str1, String str2) 
//   if (str1 != null && str2 != null) 
//     List<String> list = new ArrayList<String>();
//     String maxString = (str1.length() > str2.length()) ? str1 : str2;
//     String minString = (str1.length() > str2.length()) ? str2 : str1;
//
//     int len = minString.length();
//     for (int i = 0; i < len; i++) 
//       for (int x = 0, y = len - i; y <= len; x++, y++) 
//         String subString = minString.substring(x, y);
//         if (maxString.contains(subString)) 
//           list.add(subString);
//         
//       
//       if (list.size() != 0) 
//         break;
//       
//     
//     return list;
//   
//   return null;
// 

@Test
public void testGetMaxSameSubString() 
  String str1 = "abcwerthelloyuiodef";
  String str2 = "cvhellobnmiodef";
  String[] strs = getMaxSameSubString1(str1, str2);
  System.out.println(Arrays.toString(strs));

5️⃣题目5:对字符串中字符进行自然顺序排序

对字符串中字符进行自然顺序排序。

提示:

  • 1)字符串变成字符数组;
  • 2)对数组排序,选择,冒泡,Arrays.sort();
  • 3)将排序后的数组变成字符串。
@Test
public void testSort() 
  String str = "abcwerthelloyuiodef";
  char[] arr = str.toCharArray();
  Arrays.sort(arr);
  String newStr = new String(arr);
  System.out.println(newStr);


后记

👉Java全栈学习路线可参考:【Java全栈学习路线】最全的Java学习路线及知识清单,Java自学方向指引,内含最全Java全栈学习技术清单~
👉算法刷题路线可参考:算法刷题路线总结与相关资料分享,内含最详尽的算法刷题路线指南及相关资料分享~

开发成长之路(16)-- 算法小抄:思维跃迁

在这里插入图片描述

排序算法

在这里插入图片描述

冒泡排序:
在这里插入图片描述

复杂度分析:
在一般情况下,每一个数都要与之后的数进行匹配,所以匹配次数将与数据量n挂钩,又由于每轮匹配都要进行(n-1)次比较,所以平均时间复杂度为O(n^2)。

当然,可以对冒泡排序进行优化,比方说可以设置一个标志位,当哪次匹配没有发生数据交换时,就不用再进行后面的匹配了。
还可以做个优化,纪录下数据尾部已经稳定下的部分,比如说倒数八个数字已经稳定,那么匹配到倒数第九个数,只要和倒八匹配一下即可知道要不要往后继续匹配。

不过,冒泡排序一般也不会用在大数排序上,所以嘛,老老实实的把基础代码写好比较重要。



快速排序:
在这里插入图片描述

快速排序是很重要的算法,和傅里叶变化等算法并称二十世纪最伟大的十大算法。

快速排序的核心思维就是“分而治之”,就像封建王朝的“分封制”。将一大块“领土”,依据“嫡庶长幼”,分为不同部分,各个部分在自行细分,直到分无可分之后,便等级森严了。

说白点,就是在序列中找个元素充当中间量,大的往后,小的往前,一分为二,二分为四,四分为八···

那么,快速排序的技术核心,便呼之欲出了。其一就是这个中间量怎么找,其二就是怎么移动各个元素。

······
此外,插入、希尔、堆排、选排、归并等一系列排序方法尽在:【C++】算法集锦(1):八大排序算法 :GIF + 亲测代码 +专项练习平台


递归算法

1、明确你要干嘛
2、明确递归的结束条件
3、寻找递推关系式
4、注意边界条件与调用方式

递归中的记忆化:
在这里插入图片描述

详细了解递归算法:【C++】算法集锦(2):递归精讲


回溯算法

第 1 步都是先画图,画图是非常重要的,只有画图才能帮助我们想清楚递归结构,想清楚如何剪枝。就拿题目中的示例,想一想人手动操作是怎么做的,一般这样下来,这棵递归树都不难画出。

即在画图的过程中思考清楚:
1、分支如何产生;
2、题目需要的解在哪里?是在叶子结点、还是在非叶子结点、还是在从跟结点到叶子结点的路径?
3、哪些搜索是会产生不需要的解的?例如:产生重复是什么原因,如果在浅层就知道这个分支不能产生需要的结果,应该提前剪枝,剪枝的条件是什么,代码怎么写?

在这里插入图片描述

作者:liweiwei1419
链接:https://leetcode-cn.com/problems/permutations/solution/hui-su-suan-fa-python-dai-ma-java-dai-ma-by-liweiw/
来源:力扣(LeetCode) 著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。

更进一步了解回溯算法:【C++】算法集锦(3):回溯,从入门到入土,七道试题精选、精讲、精练


动态规划

不扯那些弯弯绕的。
第一步:画出暴力解法流程。
第二步:画出决策树(看着直观)
第三步:写出状态转移方程
第四步:决策树剪枝
第五步:再优化:确定边界

这五步列在这里,并不是说每一步都要严格的执行,我们的目标是解决问题,解决动态规划问题就需要状态转移方程,要写出好的状态转移方程就需要决策树以及决策树的剪枝优化,要画出决策树,最好有个暴力解的流程图。

不要看不起暴力求解,动态规划问题最困难的就是写出状态转移方程,即这个暴力解。优化方法无非是用备忘录或者 DP table,再无奥妙可言。

以练养学:【C++】算法集锦(4):给人看的动态规划


广度优先遍历

BFS算法和DFS算法属于图论算法的范畴,DFS在前面回溯中,可以去看一下。
BFS算法用于寻找两点之间的最短路径。

碧如说:寻找树的最小高度(迭代法)、走迷宫、导航等问题。
这些问题看起来都会比较抽象,去做也是很抽象。

与其说算法框架难写,倒不如说是把实际问题转化为算法问题来的要难。
还记得我在图论算法那篇里面有讲过:学习图论算法,最难的是要有用图论算法的意识。等下看了例题就知道了。

代码框架:

int BFS(Node start,Node target){
	/*
		这是一个BFS算法的代码框架
		return:返回从start到target的最短步数
		start:起始点
		target:终点
	*/
	
	Queue<Node> q;
	Set<Node> visited;	//避免走回头路
	
	q.offer(start);	//将起点加入队列
	visited.add(start);
	int step = 0;	//纪录扩散的步数

	while(q not empty){
		int sz = q.size();
		for(int i = 0; i<sz; i++){
			Node cur = q.poll();

			//判断是否到终点
			if(cur is target)
				return step;
			
			//将cur相邻节点加入队列
			for(Node x: cur.adj())	//cur.adj()泛指与cur相邻的节点
				if(x not in visited){
					q.offer(x);
					visited.add(x);
				}
		}	
		step++;	//更新步数
	}
}

更多详解:【C++】算法集锦(5):BFS算法


妙用快慢指针

这个就不用我多介绍吧,前面好多个“算法刷题”的文里面都一直在用了。

【C++】算法集锦(6):快慢指针


滑动窗口

给定一个含有 n 个正整数的数组和一个正整数 s ,找出该数组中满足其和 ≥ s 的长度最小的连续子数组。如果不存在符合条件的连续子数组,返回 0。

示例: 

输入: s = 7, nums = [2,3,1,2,4,3]
输出: 2
解释: 子数组 [4,3] 是该条件下的长度最小的连续子数组。

看到这个题,我不知道大家是怎么想的,我想到的就是暴力解法:
1、从头开始,以每个数字作为结果数组的头,找到刚好能大于s的结果数组。并记下结果数组中 [1:] 的和(Python写法),记为 t 。
2、如果 t 已经大于 s 了,那就结果数组头开始递减,一直减到 t 刚好小于 s 为止。
3、时刻保留一个最短子序列。
4、结果数组往后遍历一格,将值加入 t 当中。
5、回到第二步,直到结果序列的屁股顶到原序列的末位。
6、返回保留的最短子序列 的长度。

这是暴力解法吧,不知道为什么他们要叫这种解法为滑动窗口,还给出了不低的难度系数。。
如果看不懂我上面的表述,可以看图:(一图胜千言)

在这里插入图片描述

详解“滑动窗口”算法:【C++】算法集锦(7)滑动窗口


N数和问题

2sum问题:

给定一个数组,以及一个数,从数组里随即找两个数加起来等于给定的那个数。
找出每组符合条件的数(不可重复)。

这表述没有问题吧。

那,这样的题目该怎么实现呢?

如果看过上一篇,的上一篇的小伙伴应该很快就能想到用双指针吧(其实那篇我就想写这个了,但是想了想,还是憋住了)

这里有两个地方要注意:
1、数组要有序
2、跳过同类项

然后,就没什么难度了吧,我把伪代码写一下:

def two_sum(sum,nums):
	ret = []
	sz = len(nums)
	i = 0
	j = sz-1
	while i<j:
		if nums[i]+nums[j] == sum:
			ret.append([nums[1],nums[j]])
		elif nums[i]+nums[j] > sum:
			while nums[j-1] == nums[j]:
				j-=1
			j-=1
		else:
			while nums[i+1] == nums[i]:
				i+=1
			i+=1
	
	return ret

详解:【C++】算法集锦(8):从两数和问题拓展到一百数和问题


背包问题

本来要弄《背包九讲》的,然后发现实力还是不允许。

给你一个载重量为 W 的背包,以及一堆物品,这些物品都有属于自己的两个属性:价值var和质量wt,试问这个背包最多能装多少价值的物品。

这里面的每一个物品,要么装,要么不装。

看到这个图,第一反应是不是:性价比比一下。如果是这样想的朋友可以停下来了,性价比不行。
如果只有两个物品,一个4Kg,值8¥;一个15Kg,值10¥;很明显前面那个性价比高,但是显然我们要选的是后面这个。

这种题目,实在让人很懵逼,就好像千头万绪,但是所有思路都被自己给否定了。

【C++】算法集锦(9):背包问题


贪心算法

贪心算法可以理解为一种特殊的动态规划为题,拥有一些更加特殊的性质,可以进一步降低动态规划算法的时间复杂度。

【C++】算法集锦(14):贪心算法


以上是关于LeetCode算法成长之路Java字符串相关类总结与经典题目分析的主要内容,如果未能解决你的问题,请参考以下文章

gzip算法--JAVA成长之路

Java成长之路

蝙蝠的成长之路

LeetCode算法题-Rotate String(Java实现)

「成长之路」挥手2020,Chocolate 同学年度总结,所遇 | 所思 | 所学 | 所悟(年度征文)

开发成长之路(16)-- 算法小抄:思维跃迁