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 ...
随机推荐
- java课设-计算数学表达式的程序,201521123050,肖世松,个人
1.团队课程设计博客链接 http://www.cnblogs.com/xss666/p/7063780.html 2.个人负责模块或任务说明 个人负责:计算器外观,左容器CalPanelL p1: ...
- java-annotation的简单介绍
package com.yangwei.shop.entity; /** * annotation作用 一是进行标识,二是进行约束 * *///必须让它在运行时能够执行@Retention(Reten ...
- mysql 1093错误
1093错误:修改一个表的时候子查询不能是同一个表 解决办法:把子查询再套一层,变成原来表的孙子查询就可以了 例如: INSERT INTO gg SET id3=(SELECT c.a+1 FROM ...
- Git 基本命令有哪些
Git 相关命令 git init 初始化一个项目 git clone 利用url 从远程clone下来一个项目 git status 查看当前项目修改状态 git log 查看日志 查看历史记录 g ...
- cocos2dx 播放gif
起因 或许有人会说,cocos2dx中直接帧动画就行了用什么GIF. 起因是为游戏内部要用到第三方平台的头像,而第三方平台的头像大多都是用到Gif,所以才会有了这个需求 过程 查了各种文档都没找到.但 ...
- Spring c3p0连接池无法释放解决方案
通过c3p0配置连接池的时候,在进行压力测试的时候,日志出现了这样一个错误:Data source rejected establishment of connection, message from ...
- Android + HTML5 混合开发
摘要: 对于 Android + HTML5 混合开发以下的观点仅仅是我的个人观点,如果有什么不对的地方请指正 简介: 混合开发的 App(Android + HTML5)就是在一个 App 中内嵌一 ...
- node 当中的 cnpm和npm 的区别和使用
在安装nodejs之后会有npm命令 打开命令符输入之后 输入node -v(记得-v前空格)查看版本信息 如果显示出来了就说明安装成功 然后 npm 可以安装node插件 cnpm使用的是淘宝网 ...
- 查找Oracle数据库中的重复记录
本文介绍了几种快速查找ORACLE数据库中的重复记录的方法. 下面以表table_name为例,介绍三种不同的方法来确定库表中重复的记录 方法1:利用分组函数查找表中的重复行:按照某个字段分组,找出行 ...
- 安装myeclipse2015 stable 3.0破解之后发生出现SECURITY ALERT:iNTEGRITY CHECK ERROR然后闪退解决方案
安装好myeclipse2015 stable以后也一步步按着破解文件的步骤来进行.打开myEclipse---->Subscription information--->Subscrip ...