算法学习~
1、怎么把一个数字转成字符串?
int num=1;
①使用String.valueOf(num)方法
②使用包装类的toString()方法
Integer num1=num;
String str1=num1.toString();
③字符串拼接
String s=""+num;
当写完一个算法之后,运行不过的话,如果觉得代码逻辑没问题,那么就先从两个方面进行检查,是否是数值类型溢出问题,是否是算法复杂度太高而导致一部分运行超时
2、统计小写字母的频率
import java.util.Arrays;
public class test1 {
public static void main(String[] args) {
int hash []=new int[26];
String s="abracaddsfskf";
for (int i = 0; i <s.length() ; i++) {
//将字符转换成0~25的数值,转换之后,可以用作数组的索引,对应26个英文字母的位置
hash[s.charAt(i)-'a']++;//++,这是为了统计某个字符出现的次数
}
System.out.println(Arrays.toString(hash));
}
}
class Solution {
public boolean isAnagram(String s, String t) {
if (s.length() != t.length() || s.equals(t)) {
return false;
}
char[] s1 = s.toCharArray();
char[] s2 = t.toCharArray();
Arrays.sort(s1);
Arrays.sort(s2);
return Arrays.equals(s1, s2);
}
}
3、哈希法
class Solution {
public boolean isAnagram(String s, String t) {
if (s.length() != t.length() || s.equals(t)) {
return false;
}
int[] hash = new int[26];
for (int i = 0; i < s.length(); i++) {
hash[s.charAt(i) - 'a']++;
}
for (int j = 0; j < t.length(); j++) {
hash[t.charAt(j) - 'a']--;
}
for (int k = 0; k < hash.length; k++) { // 修复:k-- → k++
if (hash[k] != 0) {
return false; // 直接返回,无需flag变量
}
}
return true;
}
}
哈希表问题:数组,set,map
用map集合解决,数组元素值做键,下标做值
return new int[] {-1,-1}
用map计算出nums1+nums2的和,和做键,和出现的次数做值,nums2+nums3的值同样这样表示,然后遍历map1,找map2中键为0-x的值
import java.util.HashMap;
import java.util.Map;
public class fourSumCount {
public int fourSumCount(int[] nums1, int[] nums2, int[] nums3, int[] nums4) {
Map<Integer, Integer>map=new HashMap<>();
Map<Integer,Integer>map1=new HashMap<>();
for (int i = 0; i < nums1.length; i++) {
for (int i1 = 0; i1 < nums2.length; i1++) {
int sum1=nums1[i]+nums2[i1];
if (map.containsKey(sum1)){
map.put(sum1,map.get(sum1)+1);
}else{
map.put(sum1,1);
}
}
}
for (int i = 0; i < nums3.length; i++) {
for (int i1 = 0; i1 < nums4.length; i1++) {
int sum2=nums3[i]+nums4[i1];
if (map1.containsKey(sum2)){
map1.put(sum2,map1.get(sum2)+1);
}else{
map1.put(sum2,1);
}
}
}
int count=0;
for (Map.Entry<Integer, Integer> entry : map.entrySet()) {
if (map1.containsKey(-entry.getKey())){
count+=map1.get(-entry.getKey())*entry.getValue();
}
}
return count;
}
}
怎么把StringBuilder类型的数据转成String类型?
调用toString()方法 ;String str=sb.toString();
删除字符串前后的空格
String str=new String();
str=str.trim();//删除字符串前后的空格
KMP算法
最长相等前后缀:
在一个字符串中,既是其前缀又是其后缀的最长子串的长度,且该子串不能等于原字符串本身。具体来说:
-
前缀:从字符串开头开始的任意子串(不包括自身)。
-
后缀:从字符串末尾结束的任意子串(不包括自身)。
-
最长相等前后缀:在所有满足既是前缀又是后缀的子串中,长度最大的那个。
示例说明:
-
字符串 "abab":
-
前缀集合:
"a", "ab", "aba"
。 -
后缀集合:
"b", "ab", "bab"
。 -
最长相等前后缀为
"ab"
,长度为 2。
-
应用场景:
在KMP算法中,通过构造部分匹配表(next数组)记录每个位置的最长相等前后缀长度,用于在字符串匹配失败时快速调整模式串的位置,减少不必要的比较。
计算方法(构建next数组):
1、初始化:next[0]=0,指针j=0。
2、遍历字符串(i从1开始)
若当前字符s[i]==s[j],则j++,next[i]=j;
否则,若j>0,回退j=next[j-1];否则next[i]=0.
import java.util.Arrays;
public class Day42 {
public static void main(String[] args) {
String str="abab";
System.out.println(Arrays.toString(varcher(str)));
}
public static int[] varcher(String str){
int len = str.length();
int []next=new int[len];
next[0]=0;
int j=0;
for (int i = 1; i < len; i++) {
if (str.charAt(i)==str.charAt(j)){
j++;
next[i]=j;
}else{
if (j>0){
j=next[j-1];
}else{
next[i]=0;
}
}
}
return next;
}
}
查找子字符串在原字符串中首次出现的索引位置
Java中的indexOf
方法用于查找子字符串在原字符串中首次出现的索引位置。
KMP算法是解决字符串匹配问题的高效算法,其核心是通过预处理模式串构建next数组来跳过不必要的匹配。
1、KMP算法核心步骤
(1)构建next数组
next数组用于记录模式串(needle)每个位置的最长公共前后缀长度,帮助快速回溯。
构建方法:
-
初始化next[0]=0,双指针i=1(后缀尾),j=0(前缀尾)。
-
遍历模式串,根据字符是否匹配更新j的值:
-
匹配时:j++,next[i]=j,i++
-
不匹配时:j回退到next[j-1]
-
最终next数组几位每个位置的最长公共前缀
(2)双指针匹配
-
主指针i遍历haystack,模式指针j遍历needle。
-
当字符匹配时,双指针同时后移。
-
当不匹配时,j根据next[j-1]回退,i不动。
-
当j达到needle长度时,匹配成功。
如果一个字符串是由重复子串组成的,那么他的最小重复单位就是他的最长相等前后缀不包含的那一部分
回溯法
回溯法解决的问题
-
组合问题:N个数里面按一定规则找出k个数的集合
-
切割问题:一个字符串按一定规则有几种切割方式
-
子集问题:一个N个数的集合里有多少种符合条件的子集
-
排列问题:N个数按一定规则全排列,有几种排列方式
-
棋盘问题:N皇后,解数独等等
组合是不强调元素顺序的,排列是强调元素顺序的。
回溯法解决的问题都可以抽象为树形结构,回溯法解决的都是在结合中递归查找子集,集合的大小就构成了书的宽度,递归的深度就构成了树的深度。
void backtracking(参数){
if(终止条件){
存放结果;
return;
}
for(选择:本层集合中元素(数中节点孩子的数量就是集合的大小)){
处理节点;
backtracking(路径,选择列表);//递归
回溯,撤销处理结果
}
}