Java数据结构和算法总结-字符串及高频面试题算法
前言:周末闲来无事,看了看字符串相关算法的讲解视频,收货颇丰,跟着视频讲解简单做了一下笔记,方便以后翻阅复习同时也很乐意分享给大家。什么字符串在算法中有多重要之类的大路边上的客套话就不多说了,直接上笔记吧。
一、字符串
java:String内置类型,不可更改。(如需更改可考虑:StringBuffer, StringBuilder,char[]等)
二、归类
字符串涉及到的相关题型通常会是以下几个方面:
- 概念理解:字典序
- 简单操作:插入删除字符、旋转
- 规则判断(罗马数字转换 是否是合法的整数、浮点数)
- 数字运算(大数加法,二进制加法)
- 排序、交换
- 字符计数:变位词
- 匹配(正则表达式、全串匹配、KMP、周期判断)
- 动态规划(LCS、编辑距离、最长回文子串)
- 搜索(单词变换、排列组合)
三、例题
1、交换:把一个只包含01的串排序,可交换任意两个数的位置,最少需要多少次交换?
思路:从两头往中间扫荡,扫荡过程中在左边遇到1就和右边遇到的0交换位置,直接到左有下标相遇时结束。 具体代码如下:
public static void main(String[] strs) {
int count = ;
int[] arrays = new int[] {, , , , , , , , , };
int left = ;
int right = arrays.length - ;
while (true) {
while (arrays[left] == ) {
left++;
}
while (arrays[right] == ) {
right--;
}
if (left >= right) {
break;
} else {
int temp = arrays[left];
arrays[left] = arrays[right];
arrays[right] = temp;
count++;
}
}
Logger.println("交换次数:" + count);
for (int array : arrays) {
Logger.print(array + ", ");
}
}
清晰起见,交换次数和排序后的的字符串输出如下:
交换次数:3
0, 0, 0, 0, 0, 1, 1, 1, 1, 1,
2、字符串替换和复制:删除一个字符串所有的a,并且复制所有的b(字符数组足够大)
思路:详细思路见代码注释
public static void main(String[] strs) {
char[] input = new char[]{'a', 'b', 'c', 'd', 'a', 'f', 'a', 'b', 'c', 'd', 'b', 'b', 'a', 'b'};
char[] chars = new char[50];
for (int j = 0; j < input.length; j++) {
chars[j] = input[j];
}
Logger.println("操作前:");
for (char c:chars
) {
Logger.print(c + ", ");
}
int n = 0;
int countB = 0;
// 1、删除a,用n当做新下标,循环遍历数组,凡是不是a的元素都放到新下标的位置,由于新n增长慢,老下标i增长快,所以元素不会被覆盖。
// 并且在删除a时顺便记录b的数量,以便下一步复制b时可以提前确定数组最终的最大的下标。
for (int i = 0; chars[i] != '\u0000' && i < chars.length; i++) {
if (chars[i] != 'a') {
chars[n++] = chars[i];
}
if (chars[i] == 'b') {
countB++;
}
}
// 2、复制b,由于在第一步中就已经知道了字符串中b的个数,这里就能确定最终字符串的最大下标,从最打下表开始倒着复制原字符串,碰到b时复制即可。
int newMaxIndex = n + countB - 1;
for (int k = n - 1; k >= 0; k--) {
chars[newMaxIndex--] = chars[k];
if (chars[k] == 'b') {
chars[newMaxIndex--] = chars[k];
}
}
Logger.println("\n操作后:");
for (char c:chars
) {
Logger.print(c + ", ");
}
}
3、交换星号:一个字符串只包含 * 和数字,请把它的 * 都放在开头。
如:1 * 2 * 4 * 3 => * * * 1 2 4 3
- 方案一:倒着操作,从最大下标开始向前遍历,遇到非 * 号的元素则加入"新"下标中,遍历完毕后,j即代表 * 号的个数,然后将0-j赋值为 * 即可。(操作后,数字的相对位置不变) 代码如下:
public static void main(String[] strs) {
char[] chars = new char[]{'1', '*', '4', '3', '*', '5', '*'};
// 方案一(操作后,数字的相对位置不变)
// 倒着操作:从最大下标开始向前遍历,遇到非*号的元素则加入"新"下标中,遍历完毕后,j即代表*号的个数,然后将0-j赋值为*即可。
int j = chars.length - 1;
for (int i = j; i >= 0; i--) {
if (chars[i] != '*') {
chars[j--] = chars[i];
}
}
while (j >= 0) {
chars[j--] = '*';
}
for (char c:chars
) {
Logger.print(c + ", ");
}
}
输出结果如下:
*, *, *, 1, 4, 3, 5,
- 方案二(操作后,数组的相对位置会变)快排划分,根据循环不变式(每一步循环之后条件都成立):如本题[0..i-1]是*,[i..j-1]是数字,[j...n-1]未探测,循环时,随着i和j增加,维护此条件依然不变,代码如下:
public static void main(String[] strs) {
char[] chars = new char[]{'1', '*', '4', '3', '*', '5', '*'};
// 方案二(操作后,数组的相对位置会变)
// 快排划分,根据循环不变式(每一步循环之后条件都成立):如本题[0..i-1]是*,[i..j-1]是数字,[j...n-1]未探测,循环时,随着i和j增加,维护此条件依然不变
for (int i = 0, j = 0; j < chars.length; ++j) {
if (chars[j] == '*') {
char temp = chars[i];
chars[i] = chars[j];
chars[j] = temp;
i++;
}
}
for (char c:chars
) {
Logger.print(c + ", ");
}
}
输出结果如下:
*, *, *, 3, 1, 5, 4,
4、单词翻转
例如:I am a student =》 student a am I
思路:
1、先将整个字符串翻转:如:I am a student =》 tneduts a ma I
2、通过空格判断出每个单词,然后对每个单词进行翻转
代码如下:
public static void main(String[] strs) {
String input = "I am a student";
char[] chars = input.toCharArray();
int i = 0;
int j = chars.length - 1;
while (i < j) {
swap(chars, i++, j--);
}
int front = 1;
int tail = 0;
while (front < chars.length) {
if (chars[front] == ' ') {
int frontTemp = front - 1;
while (tail < frontTemp) {
swap(chars, tail++, frontTemp--);
}
tail = front + 1;
}
front++;
}
for (char c:chars
) {
Logger.print(c);
}
}
public static void swap(char[] chars, int index1, int index2) {
char temp = chars[index1];
chars[index1] = chars[index2];
chars[index2] = temp;
}
输出结果如下:
student a am I
5、子串变位词:给定两个串a和b,问b是否a的子串变位词。
例如:a=hello。b=lel,lle,ello都是true;b=elo是false
思路:
- 一、首先需要了解对两个串是否是变位词的判断:
- 对两个串按统一规则排序,排序后若相等则是变位词。
- 对两个串中出现的字母统计,两串中相同的字母出现的次数一致则为变位词。
- 二、然后从母串的第一个元素遍历,每往后遍历一个元素就把从当前元素开始到加上子串的长度的位置作为一个区间和子串比较是否是变位词。
最后一题综合前几个题用到的一些技巧,还是比较有趣的,这里就不贴出代码了,也激发一下大家的动手能力,感兴趣的童鞋不妨试着写一写。
以上问题如有不同思路欢迎交流。
Java数据结构和算法总结-字符串及高频面试题算法的更多相关文章
- Java数据结构和算法总结-字符串相关高频面试题算法
前言:周末闲来无事,看了看字符串相关算法的讲解视频,收货颇丰,跟着视频讲解简单做了一下笔记,方便以后翻阅复习同时也很乐意分享给大家.什么字符串在算法中有多重要之类的大路边上的客套话就不多说了,直接上笔 ...
- 2020年Java多线程与并发系列22道高频面试题(附思维导图和答案解析)
前言 现在不管是大公司还是小公司,去面试都会问到多线程与并发编程的知识,大家面试的时候这方面的知识一定要提前做好储备. 关于多线程与并发的知识总结了一个思维导图,分享给大家 1.Java中实现多线程有 ...
- xsank的快餐 » Python simhash算法解决字符串相似问题
xsank的快餐 » Python simhash算法解决字符串相似问题 Python simhash算法解决字符串相似问题
- ipv4 ipv6 求字符串和整数一一映射的算法 AmazonOrderId
字符串和整数一一映射的算法 公司每人的英文名不同,现在给每个英文名一个不同的数字编号,怎么设计? 走ipv4/6 2/32 2/128就够了,把“网段”概念对应到“表或库”,ip有a_e5类,这概念 ...
- Java数据结构和算法 - 堆
堆的介绍 Q: 什么是堆? A: 这里的“堆”是指一种特殊的二叉树,不要和Java.C/C++等编程语言里的“堆”混淆,后者指的是程序员用new能得到的计算机内存的可用部分 A: 堆是有如下特点的二叉 ...
- Java数据结构和算法 - 栈和队列
Q: 栈.队列与数组的区别? A: 本篇主要涉及三种数据存储类型:栈.队列和优先级队列,它与数组主要有如下三个区别: A: (一)程序员工具 数组和其他的结构(栈.队列.链表.树等等)都适用于数据库应 ...
- Java数据结构与算法 - 外部存储
Q: 什么是外部存储? A: 外部存储特指某类磁盘系统,例如在大多数台式电脑或服务器中的硬盘. Q: 如何访问外部存储? A: 我们所学的数据结构都是假设数据存储在内存中,但是,在很多情况下要处理的数 ...
- Java数据结构和算法 - 哈希表
Q: 如何快速地存取员工的信息? A: 假设现在要写一个程序,存取一个公司的员工记录,这个小公司大约有1000个员工,每个员工记录需要1024个字节的存储空间,因此整个数据库的大小约为1MB.一般的计 ...
- Java数据结构和算法(一)--栈
栈: 英文名stack,特点是只允许访问最后插入的那个元素,也就是LIFO(后进先出) jdk中的stack源码: public class Stack<E> extends Vector ...
随机推荐
- 201521123061 《Java程序设计》第四周学习总结
201521123061 <Java程序设计>第四周学习总结 1. 本章学习总结 (1)思维导图: --- (2)上课内容总结: 第四周学习了Java中的继承与多态,思维导图中已经给出了本 ...
- 201521123037 《Java程序设计》第2周学习总结
1. 本周学习总结 初步学会分析使用命令提示符进行编译的命令 了解使用import引入不同包的类 学会码云与eclipse的连接 使用Array和String函数编写程序 2. 书面作业 1. 使用E ...
- 201521123053《Java程序设计》第十周学习总结
---恢复内容开始--- 1. 本周学习总结 1.1 以你喜欢的方式(思维导图或其他)归纳总结异常与多线程相关内容. 在java多线程程序中,所有线程都不允许抛出未捕获的checked excepti ...
- 201521123012 《Java程序设计》第十四周学习总结
1. 本周学习总结 1.1 以你喜欢的方式(思维导图或其他)归纳总结多数据库相关内容. 2. 书面作业 1. MySQL数据库基本操作 1.1建立数据库,将自己的姓名.学号作为一条记录插入.(截图, ...
- 201521123028 《Java程序设计》第12周学习总结
1. 本周学习总结 流与文件 I/O流:Input/Output处理的简称,本质上就是一个数据序列.分为输入流Input Stream和输出流Output Stream. 最基本的可处理数据单位-by ...
- dbda数据库类
<?phpclass DBDA{ public $host="localhost";//服务器地址 public $uid="root";//用户名 pu ...
- 201621123088《Java程序设计》第1周学习总结
1.本周学习总结 以几个关键词描述本周的学习内容.并阐述关键概念之间的联系. 这周是我第一次学习Java,对于我这个上学期没有学好的人来说,Java无疑是一个新的噩梦,但是我相信我这学期一定能学好Ja ...
- 聊聊JAVA中 String类为什么不可变
前言 "我的风格比较偏传统和经典" 小明说,"我们在打扮自己的问题上还是蛮冒险的...我觉得当你是只狗的时候,穿什么都hold的住!" 哈哈哈,脱离单身狗快两年 ...
- 06jQuery-01-基本选择器
1.jQuery概要 JavaScript的一个库,只是一个jquery-xxx.js的文件,它可以让你写更少的代码,做更多的事. $是著名的jQuery符号.实际上,jQuery把所有功能全部封装在 ...
- 详解go语言的array和slice 【二】
上一篇已经讲解过,array和slice的一些基本用法,使用array和slice时需要注意的地方,特别是slice需要注意的地方比较多.上一篇的最后讲解到创建新的slice时使用第三个索引来限制sl ...