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

一、字符串

  • java:String内置类型,不可更改。(如需更改可考虑:StringBuffer, StringBuilder,char[]等)

二、归类

 字符串涉及到的相关题型通常会是以下几个方面:

  • 概念理解:字典序
  • 简单操作:插入删除字符、旋转
  • 规则判断(罗马数字转换 是否是合法的整数、浮点数)
  • 数字运算(大数加法,二进制加法)
  • 排序、交换
  • 字符计数:变位词
  • 匹配(正则表达式、全串匹配、KMP、周期判断)
  • 动态规划(LCS、编辑距离、最长回文子串)
  • 搜索(单词变换、排列组合)

三、例题

1、交换:把一个只包含01的串排序,可交换任意两个数的位置,最少需要多少次交换?

  思路:从两头往中间扫荡,扫荡过程中在左边遇到1就和右边遇到的0交换位置,直接到左有下标相遇时结束。 具体代码如下:

  1. public static void main(String[] strs) {
  2. int count = ;
  3. int[] arrays = new int[] {, , , , , , , , , };
  4. int left = ;
  5. int right = arrays.length - ;
  6. while (true) {
  7. while (arrays[left] == ) {
  8. left++;
  9. }
  10. while (arrays[right] == ) {
  11. right--;
  12. }
  13. if (left >= right) {
  14. break;
  15. } else {
  16. int temp = arrays[left];
  17. arrays[left] = arrays[right];
  18. arrays[right] = temp;
  19. count++;
  20. }
  21. }
  22. Logger.println("交换次数:" + count);
  23. for (int array : arrays) {
  24. Logger.print(array + ", ");
  25. }
  26. }

清晰起见,交换次数和排序后的的字符串输出如下:

  1. 交换次数:3
  2. 0, 0, 0, 0, 0, 1, 1, 1, 1, 1,

2、字符串替换和复制:删除一个字符串所有的a,并且复制所有的b(字符数组足够大)

  思路:详细思路见代码注释

  1. public static void main(String[] strs) {
  2. char[] input = new char[]{'a', 'b', 'c', 'd', 'a', 'f', 'a', 'b', 'c', 'd', 'b', 'b', 'a', 'b'};
  3. char[] chars = new char[50];
  4. for (int j = 0; j < input.length; j++) {
  5. chars[j] = input[j];
  6. }
  7. Logger.println("操作前:");
  8. for (char c:chars
  9. ) {
  10. Logger.print(c + ", ");
  11. }
  12. int n = 0;
  13. int countB = 0;
  14. // 1、删除a,用n当做新下标,循环遍历数组,凡是不是a的元素都放到新下标的位置,由于新n增长慢,老下标i增长快,所以元素不会被覆盖。
  15. // 并且在删除a时顺便记录b的数量,以便下一步复制b时可以提前确定数组最终的最大的下标。
  16. for (int i = 0; chars[i] != '\u0000' && i < chars.length; i++) {
  17. if (chars[i] != 'a') {
  18. chars[n++] = chars[i];
  19. }
  20. if (chars[i] == 'b') {
  21. countB++;
  22. }
  23. }
  24.  
  25. // 2、复制b,由于在第一步中就已经知道了字符串中b的个数,这里就能确定最终字符串的最大下标,从最打下表开始倒着复制原字符串,碰到b时复制即可。
  26. int newMaxIndex = n + countB - 1;
  27. for (int k = n - 1; k >= 0; k--) {
  28. chars[newMaxIndex--] = chars[k];
  29. if (chars[k] == 'b') {
  30. chars[newMaxIndex--] = chars[k];
  31. }
  32. }
  33.  
  34. Logger.println("\n操作后:");
  35. for (char c:chars
  36. ) {
  37. Logger.print(c + ", ");
  38. }
  39. }

3、交换星号:一个字符串只包含 * 和数字,请把它的 * 都放在开头。

  如:1 * 2 * 4 * 3 => * * * 1 2 4 3

  • 方案一:倒着操作,从最大下标开始向前遍历,遇到非 * 号的元素则加入"新"下标中,遍历完毕后,j即代表 * 号的个数,然后将0-j赋值为 * 即可。(操作后,数字的相对位置不变) 代码如下:
  1. public static void main(String[] strs) {
  2. char[] chars = new char[]{'1', '*', '4', '3', '*', '5', '*'};
  3. // 方案一(操作后,数字的相对位置不变)
  4. // 倒着操作:从最大下标开始向前遍历,遇到非*号的元素则加入"新"下标中,遍历完毕后,j即代表*号的个数,然后将0-j赋值为*即可。
  5. int j = chars.length - 1;
  6. for (int i = j; i >= 0; i--) {
  7. if (chars[i] != '*') {
  8. chars[j--] = chars[i];
  9. }
  10. }
  11. while (j >= 0) {
  12. chars[j--] = '*';
  13. }
  14. for (char c:chars
  15. ) {
  16. Logger.print(c + ", ");
  17. }
  18. }

输出结果如下:

  1. *, *, *, 1, 4, 3, 5,
  • 方案二(操作后,数组的相对位置会变)快排划分,根据循环不变式(每一步循环之后条件都成立):如本题[0..i-1]是*,[i..j-1]是数字,[j...n-1]未探测,循环时,随着i和j增加,维护此条件依然不变,代码如下:
  1. public static void main(String[] strs) {
  2. char[] chars = new char[]{'1', '*', '4', '3', '*', '5', '*'};
  3. // 方案二(操作后,数组的相对位置会变)
  4. // 快排划分,根据循环不变式(每一步循环之后条件都成立):如本题[0..i-1]是*,[i..j-1]是数字,[j...n-1]未探测,循环时,随着i和j增加,维护此条件依然不变
  5. for (int i = 0, j = 0; j < chars.length; ++j) {
  6. if (chars[j] == '*') {
  7. char temp = chars[i];
  8. chars[i] = chars[j];
  9. chars[j] = temp;
  10. i++;
  11. }
  12. }
  13. for (char c:chars
  14. ) {
  15. Logger.print(c + ", ");
  16. }
  17. } 

输出结果如下:

  1. *, *, *, 3, 1, 5, 4,

4、单词翻转

  例如:I am a student =》 student a am I

  思路:

  1、先将整个字符串翻转:如:I am a student =》 tneduts a ma I

  2、通过空格判断出每个单词,然后对每个单词进行翻转

  代码如下:

  1. public static void main(String[] strs) {
  2. String input = "I am a student";
  3. char[] chars = input.toCharArray();
  4. int i = 0;
  5. int j = chars.length - 1;
  6. while (i < j) {
  7. swap(chars, i++, j--);
  8. }
  9. int front = 1;
  10. int tail = 0;
  11. while (front < chars.length) {
  12. if (chars[front] == ' ') {
  13. int frontTemp = front - 1;
  14. while (tail < frontTemp) {
  15. swap(chars, tail++, frontTemp--);
  16. }
  17. tail = front + 1;
  18. }
  19. front++;
  20. }
  21. for (char c:chars
  22. ) {
  23. Logger.print(c);
  24. }
  25. }
  26.  
  27. public static void swap(char[] chars, int index1, int index2) {
  28. char temp = chars[index1];
  29. chars[index1] = chars[index2];
  30. chars[index2] = temp;
  31. }

输出结果如下:

  1. 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. Java常用类之【字符串相关类型】

    一.字符相关类型 分类: 1.不可变的字符序列: String类 2.可变的字符序列: StringBuilder类--->线程不安全的 执行效率相对较高 StringBuffer类---> ...

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

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

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

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

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

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

  6. 【Todo】字符串相关的各种算法,以及用到的各种数据结构,包括前缀树后缀树等各种树

    另开一文分析字符串相关的各种算法,以及用到的各种数据结构,包括前缀树后缀树等各种树. 先来一个汇总, 算法: 本文中提到的字符串匹配算法有:KMP, BM, Horspool, Sunday, BF, ...

  7. 【Java数据结构学习笔记之二】Java数据结构与算法之栈(Stack)实现

      本篇是java数据结构与算法的第2篇,从本篇开始我们将来了解栈的设计与实现,以下是本篇的相关知识点: 栈的抽象数据类型 顺序栈的设计与实现 链式栈的设计与实现 栈的应用 栈的抽象数据类型   栈是 ...

  8. Java数据结构和算法(九)——高级排序

    春晚好看吗?不存在的!!! 在Java数据结构和算法(三)——冒泡.选择.插入排序算法中我们介绍了三种简单的排序算法,它们的时间复杂度大O表示法都是O(N2),如果数据量少,我们还能忍受,但是数据量大 ...

  9. java数据结构与算法之栈(Stack)设计与实现

    本篇是java数据结构与算法的第4篇,从本篇开始我们将来了解栈的设计与实现,以下是本篇的相关知识点: 栈的抽象数据类型 顺序栈的设计与实现 链式栈的设计与实现 栈的应用 栈的抽象数据类型 栈是一种用于 ...

随机推荐

  1. Window PHP 使用命令行模式

    电脑系统: win7 php环境: phpstudy 1 把php目录放到环境变量path下面: 我的电脑->属性->高级->环境变量->系统变量->Path->编 ...

  2. java高级---->Thread之BlockingQueue的使用

    今天我们通过实例来学习一下BlockingQueue的用法.梦想,可以天花乱坠,理想,是我们一步一个脚印踩出来的坎坷道路. BlockingQueue的实例 官方文档上的对于BlockingQueue ...

  3. 【黑金ZYNQ7000系列原创视频教程】07.自定义IP——定制RTC IP实验

    黑金论坛地址: http://www.heijin.org/forum.php?mod=viewthread&tid=36641&extra=page%3D1 爱奇艺地址: http: ...

  4. centos7上开启单用户模式

    author: headsen  chen date : 2018-08-02  11:23:16 1,在出现centos7的页面的时候,按 e进入到编译内核的界面 2,找到下面的这一段,将ro 该车 ...

  5. vim命令删除后重新安装

    个人原创博客,转载请注明,否则追究法律责任 2017-09-30-09:51:20 1,删除vim命令.模拟错误 [root@localhost ~]# which vim/usr/bin/vim[r ...

  6. 【BZOJ3932】[CQOI2015]任务查询系统 主席树

    [BZOJ3932][CQOI2015]任务查询系统 Description 最近实验室正在为其管理的超级计算机编制一套任务管理系统,而你被安排完成其中的查询部分.超级计算机中的 任务用三元组(Si, ...

  7. Redis集群管理(二)

    1.进入集群客户端 任意选一个redis节点,进入redis 所在目录 cd /redis 所在目录/src/ ./redis-cli -h 本地节点的ip -p redis的端口号 -a 密码 [r ...

  8. 报警告session_regenerate_id(): Failed to create(read) session ID: files (path: N;/path)

    php.ini文件中的session.save_path = "N;/path"注释掉(前面加分号)

  9. 2.title

    1.母版页里写title,标题会:会显示母版页里的. 结果如下: 2.母版页和实现模板页同时都设置了title,会显示实现模板页里的title 运行结果页:

  10. python重定向sys.stdin、sys.stdout和sys.stderr

    转自:https://www.cnblogs.com/guyuyuan/p/6885448.html 标准输入.标准输出和错误输出. 标准输入:一般是键盘.stdin对象为解释器提供输入字符流,一般使 ...