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 ...
随机推荐
- 201521123070 《JAVA程序设计》第4周学习总结
1. 本章学习总结 1.1 尝试使用思维导图总结有关继承的知识点. http://naotu.baidu.com/file/4de6f42e4f4f6cce0531dd9997b04e60?token ...
- 201521123077 《Java程序设计》第1周学习总结
1. 本章学习总结 java语言的历史 dos下运行 java文件 Math ,String ,Scanner,Interger等常用类的使用 jdk,jre,jvm等概念的了解 classpath, ...
- Js前端传递json数组至服务器端并解析的实现。
最近做的一个小项目中需要将json数组数据传递到服务器端进行保存,现分享一下解决思路. 环境:EasyUi+Mvc 4.0 如下: 在上述截图中的红色圈起来的部分,需要在点击保存后通过一次ajax请求 ...
- Codeforces Round #436 (Div. 2) C. Bus
http://codeforces.com/contest/864/problem/C 题意: 坐标轴上有x = 0和 x = a两点,汽车从0到a之后掉头返回,从a到0之后又掉头驶向a...从0到a ...
- 转自知乎(JAVA后台开发可以纯粹用JAVA SE吗?)
著作权归作者所有.商业转载请联系作者获得授权,非商业转载请注明出处.作者:巴多崽链接:http://www.zhihu.com/question/29663744/answer/45154839来源: ...
- DIY智能家居——零基础入门篇
概要 本文主要根据笔者从零开始接触硬件,以小白视角开启IoT探索,根据相关资料DIY一个温湿度传感器.后经过探索发现新大陆--Home Assistant&Homebridge,最终实现了一个 ...
- Codeforces Round #420 (Div. 2)
/*************************************************************************************************** ...
- Tomcat服务器如何读取本地磁盘数据?
实际问题: 如何让用户下载本地磁盘的资源文件呢? 在server.xml文件中配置虚拟路径如下(以下代码放在Host标签之中即可): 例如: 具体含义: 把本地磁盘目录 "D:\uploa ...
- 通过npm写一个cli命令行工具
前言 如果你想写一个npm插件,如果你想通过命令行来简化自己的操作,如果你也是个懒惰的人,那么这篇文章值得一看. po主的上一篇文章介绍了定制自己的模版,但这样po主还是不满足啊,项目中我们频繁的需要 ...
- js中 && 与 || 的妙用
在js逻辑运算中,0."".null.false.undefined.NaN都会判为false,其他都为true(好像没有遗漏了吧,请各位确认下).这个一定要记住,不然应用||和& ...