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

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

一、字符串

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

二、归类

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

概念理解:字典序

简单操作:插入删除字符、旋转

规则判断(罗马数字转换 是否是合法的整数、浮点数)

数字运算(大数加法,二进制加法)

排序、交换

字符计数:变位词

匹配(正则表达式、全串匹配、KMP、周期判断)

动态规划(LCS、编辑距离、最长回文子串)

搜索(单词变换、排列组合)

三、例题

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

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

1 public static voidmain(String[] strs) {2 int count = 0;3 int[] arrays = new int[] {0, 0, 1, 1, 1, 0, 1, 0, 0, 1};4 int left = 0;5 int right = arrays.length - 1;6 while (true) {7 while (arrays[left] == 0) {8 left++;9 }10 while (arrays[right] == 1) {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 (intarray : arrays) {24 Logger.print(array + ",");25 }26 }

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

交换次数:3

0, 0, 0, 0, 0, 1, 1, 1, 1, 1,

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

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

1 public static voidmain(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 (charc:chars9 ) {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 (charc:chars36 ) {37 Logger.print(c + ", ");38 }39 }

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

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

方案一:倒着操作,从最大下标开始向前遍历,遇到非 * 号的元素则加入"新"下标中,遍历完毕后,j即代表 * 号的个数,然后将0-j赋值为 * 即可。(操作后,数字的相对位置不变) 代码如下:

1 public static voidmain(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 (charc:chars15 ) {16 Logger.print(c + ", ");17 }18 }

输出结果如下:

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

方案二(操作后,数组的相对位置会变)快排划分,根据循环不变式(每一步循环之后条件都成立):如本题[0..i-1]是*,[i..j-1]是数字,[j...n-1]未探测,循环时,随着i和j增加,维护此条件依然不变,代码如下:

1 public static voidmain(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 (charc:chars14 ) {15 Logger.print(c + ", ");16 }17 }

输出结果如下:

*, *, *, 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 voidmain(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

27 public static void swap(char[] chars, int index1, intindex2) {28 char temp =chars[index1];29 chars[index1] =chars[index2];30 chars[index2] =temp;31 }

输出结果如下:

student a am I

5、子串变位词:给定两个串a和b,问b是否a的子串变位词。

例如:a=hello。b=lel,lle,ello都是true;b=elo是false

思路:

一、首先需要了解对两个串是否是变位词的判断:

对两个串按统一规则排序,排序后若相等则是变位词。

对两个串中出现的字母统计,两串中相同的字母出现的次数一致则为变位词。

二、然后从母串的第一个元素遍历,每往后遍历一个元素就把从当前元素开始到加上子串的长度的位置作为一个区间和子串比较是否是变位词。

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

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

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
1.算法是程序的灵魂,优秀的程序在对海量数据处理时,依然保持高速计算,就需要高效的数据结构算法支撑。2.网上数据结构算法的课程不少,但存在两个问题:1)授课方式单一,大多是照着代码念一遍,数据结构算法本身就比较难理解,对基础好的学员来说,还好一点,对基础不好的学生来说,基本上就是听天书了2)说是讲数据结构算法,但大多是挂羊头卖狗肉,算法讲的很少。 本课程针对上述问题,有针对性的进行了升级 3)授课方式采用图解+算法游戏的方式,让课程生动有趣好理解 4)系统全面的讲解了数据结构算法, 除常用数据结构算法外,还包括程序员常用10大算法:二分查找算法(非递归)、分治算法、动态规划算法、KMP算法、贪心算法、普里姆算法、克鲁斯卡尔算法、迪杰斯特拉算法、弗洛伊德算法、马踏棋盘算法。可以解决面试遇到的最短路径、最小生成树、最小连通图、动态规划等问题及衍生出的面试题,让你秒杀其他面试小伙伴3.如果你不想永远都是代码工人,就需要花时间来研究下数据结构算法。教程内容:本教程是使用Java来讲解数据结构算法,考虑到数据结构算法较难,授课采用图解加算法游戏的方式。内容包括: 稀疏数组、单向队列、环形队列、单向链表、双向链表、环形链表、约瑟夫问题、栈、前缀、中缀、后缀表达式、中缀表达式转换为后缀表达式、递归与回溯、迷宫问题、八皇后问题、算法的时间复杂度、冒泡排序、选择排序、插入排序、快速排序、归并排序、希尔排序、基数排序(桶排序)、堆排序、排序速度分析、二分查找、插值查找、斐波那契查找、散列、哈希表、二叉树、二叉树与数组转换、二叉排序树(BST)、AVL树、线索二叉树、赫夫曼树、赫夫曼编码、多路查找树(B树B+树和B*树)、图、图的DFS算法和BFS、程序员常用10大算法、二分查找算法(非递归)、分治算法、动态规划算法、KMP算法、贪心算法、普里姆算法、克鲁斯卡尔算法、迪杰斯特拉算法、弗洛伊德算法马踏棋盘算法。学习目标:通过学习,学员能掌握主流数据结构算法的实现机制,开阔编程思路,提高优化程序的能力。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值