前言:周末闲来无事,看了看字符串相关算法的讲解视频,收货颇丰,跟着视频讲解简单做了一下笔记,方便以后翻阅复习同时也很乐意分享给大家。什么字符串在算法中有多重要之类的大路边上的客套话就不多说了,直接上笔记吧。

一、字符串

  • 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

  思路:

    •   一、首先需要了解对两个串是否是变位词的判断:
    1.   对两个串按统一规则排序,排序后若相等则是变位词。
    2.   对两个串中出现的字母统计,两串中相同的字母出现的次数一致则为变位词。
    •   二、然后从母串的第一个元素遍历,每往后遍历一个元素就把从当前元素开始到加上子串的长度的位置作为一个区间和子串比较是否是变位词。

最后一题综合前几个题用到的一些技巧,还是比较有趣的,这里就不贴出代码了,也激发一下大家的动手能力,感兴趣的童鞋不妨试着写一写。

以上问题如有不同思路欢迎交流。

Java数据结构和算法总结-字符串及高频面试题算法的更多相关文章

  1. Java数据结构和算法总结-字符串相关高频面试题算法

    前言:周末闲来无事,看了看字符串相关算法的讲解视频,收货颇丰,跟着视频讲解简单做了一下笔记,方便以后翻阅复习同时也很乐意分享给大家.什么字符串在算法中有多重要之类的大路边上的客套话就不多说了,直接上笔 ...

  2. 2020年Java多线程与并发系列22道高频面试题(附思维导图和答案解析)

    前言 现在不管是大公司还是小公司,去面试都会问到多线程与并发编程的知识,大家面试的时候这方面的知识一定要提前做好储备. 关于多线程与并发的知识总结了一个思维导图,分享给大家 1.Java中实现多线程有 ...

  3. xsank的快餐 » Python simhash算法解决字符串相似问题

    xsank的快餐 » Python simhash算法解决字符串相似问题 Python simhash算法解决字符串相似问题

  4. ipv4 ipv6 求字符串和整数一一映射的算法 AmazonOrderId

    字符串和整数一一映射的算法 公司每人的英文名不同,现在给每个英文名一个不同的数字编号,怎么设计? 走ipv4/6  2/32 2/128就够了,把“网段”概念对应到“表或库”,ip有a_e5类,这概念 ...

  5. Java数据结构和算法 - 堆

    堆的介绍 Q: 什么是堆? A: 这里的“堆”是指一种特殊的二叉树,不要和Java.C/C++等编程语言里的“堆”混淆,后者指的是程序员用new能得到的计算机内存的可用部分 A: 堆是有如下特点的二叉 ...

  6. Java数据结构和算法 - 栈和队列

    Q: 栈.队列与数组的区别? A: 本篇主要涉及三种数据存储类型:栈.队列和优先级队列,它与数组主要有如下三个区别: A: (一)程序员工具 数组和其他的结构(栈.队列.链表.树等等)都适用于数据库应 ...

  7. Java数据结构与算法 - 外部存储

    Q: 什么是外部存储? A: 外部存储特指某类磁盘系统,例如在大多数台式电脑或服务器中的硬盘. Q: 如何访问外部存储? A: 我们所学的数据结构都是假设数据存储在内存中,但是,在很多情况下要处理的数 ...

  8. Java数据结构和算法 - 哈希表

    Q: 如何快速地存取员工的信息? A: 假设现在要写一个程序,存取一个公司的员工记录,这个小公司大约有1000个员工,每个员工记录需要1024个字节的存储空间,因此整个数据库的大小约为1MB.一般的计 ...

  9. Java数据结构和算法(一)--栈

    栈: 英文名stack,特点是只允许访问最后插入的那个元素,也就是LIFO(后进先出) jdk中的stack源码: public class Stack<E> extends Vector ...

随机推荐

  1. 201521123063 《JAVA程序设计》 第5周学习总结

    1. 本周学习总结 1.1 尝试使用思维导图总结有关多态与接口的知识点. 1.2 可选:使用常规方法总结其他上课内容. 上周学习了继承和多态,满足is-a条件,但是发现会导致继承的滥用,如果只是但以的 ...

  2. VBScript中Msgbox函数的用法

    MsgBox(prompt[, buttons][, title][, helpfile, context]) [用途]:弹出对话框,并获取用户的操作结果. [参数说明]: propmt:对话框中展示 ...

  3. 201521123038 《Java程序设计》 第十二周学习总结

    201521123038 <Java程序设计> 第十二周学习总结 1. 本周学习总结 1.1 以你喜欢的方式(思维导图或其他)归纳总结多流与文件相关内容. 2. 书面作业 将Student ...

  4. 201521123025《java程序设计》第13周学习总结

    1. 本周学习总结 2. 书面作业 1. 网络基础 1.1 比较ping www.baidu.com与ping cec.jmu.edu.cn,分析返回结果有何不同?为什么会有这样的不同? 从结果来看, ...

  5. 201521123117 《Java程序设计》第13周学习总结

    1. 本周学习总结 2. 书面作业 1. 网络基础 1.1 比较ping www.baidu.com与ping cec.jmu.edu.cn,分析返回结果有何不同?为什么会有这样的不同? 分析结果:从 ...

  6. 201521123022 《Java程序设计》 第九周学习总结

    1.本章学习总结 2. 书面作业 本次PTA作业题集异常 1.常用异常 题目5-1 Q1.1 截图你的提交结果(出现学号) Q1.2 自己以前编写的代码中经常出现什么异常.需要捕获吗(为什么)?应如何 ...

  7. Java课程设计-计算器 丁树乐(201521123024)

    1.团队课程设计博客链接 http://www.cnblogs.com/br0823/p/7064407.html 2.个人负责模块或任务说明 界面优化 各类之间拼接 3.自己的代码提交记录截图 4. ...

  8. 【SQL】- 基础知识梳理(六) - 游标

    游标的概念 结果集,结果集就是select查询之后返回的所有行数据的集合. 游标(Cursor): 是处理数据的一种方法. 它可以定位到结果集中的某一行,对数据进行读写. 也可以移动游标定位到你需要的 ...

  9. websocket的理解及实例应用

    websocket协议是HTML5提出的一个新的规范,主要用于实现服务器及时推送信息给客户端的功能. websocket实现是基于HTTP协议的部分握手功能,但是websocket仅仅握手一次即可进行 ...

  10. 《HelloGitHub》第 18 期

    <HelloGitHub>第 18 期 兴趣是最好的老师,HelloGitHub 就是帮你找到兴趣! 简介 分享 GitHub 上有趣.入门级的开源项目. 这是一个面向编程新手.热爱编程. ...