笔试题—字符串常见的算法题集锦

  • @param c

  • @return

*/

private static int[] getNextVal(String c) {

int[] nextVal = new int[c.length() + 1];

int front = 0;

int behind = 1;

nextVal[1] = 0;

/**

  • c.charAt(front-1)表示前缀字符 ,c.charAt(behind-1)表示后缀字符

*/

while (behind < c.length()) {

if (front == 0 || c.charAt(front - 1) == c.charAt(behind - 1)) {

++front;

++behind;

if (c.charAt(front - 1) != c.charAt(behind - 1)) {

nextVal[behind] = front;

} else {

nextVal[behind] = nextVal[front];

}

} else {

// 前缀索引回溯

front = nextVal[front];

}

}

return nextVal;

}

/**

  • 注意这里为了保持保持一致性 ,第一个next[0]没有用到

  • @param c

  • @return

*/

private static int[] getNext(String c) {

int[] next = new int[c.length() + 1];

int front = 0;

int behind = 1;

next[1] = 0;

/**

  • c.charAt(front-1)表示前缀字符 c.charAt(behind-1)表示后缀字符

*/

while (behind < c.length()) {

if (front == 0 || c.charAt(front - 1) == c.charAt(behind - 1)) {

++front;

++behind;

next[behind] = front;

} else {

// 前缀 索引回溯

front = next[front];

}

}

return next;

}

public static int matchNextVal(String source, String c, int pos) {

int i;

int[] nextVal = getNextVal©;

if (pos < 1) {

i = 1;

} else {

i = pos + 1;

}

int j = 1; // i控制S,j控制T;

while (i <= source.length() && j <= c.length()) {

if (j == 0 || source.charAt(i - 1) == c.charAt(j - 1)) {

++i;

++j;

} else {

j = nextVal[j]; // j退回合适的位置,i值不变

}

}

if (j > c.length())

return i - c.length() - 1;

else

return -1;

}

public static int matchNext(String source, String c, int pos) {

int i;

int[] next = getNext©;

if (pos < 1) {

i = 1;

} else {

i = pos + 1;

}

int j = 1; // i控制S,j控制T;

while (i <= source.length() && j <= c.length()) {

if (j == 0 || source.charAt(i - 1) == c.charAt(j - 1)) {

++i;

++j;

} else {

j = next[j]; // j退回合适的位置,i值不变

}

}

if (j > c.length())

return i - c.length() - 1;

else

return -1;

}

}


字符串倒序输出,单词不倒序


题目

对字符串中的所有单词进行倒排。

说明:

1、每个单词是以26个大写或小写英文字母构成,可能含有非法字符

2、非构成单词的字符均视为单词间隔符;

3、要求倒排后的单词间隔符以一个空格表示;如果原字符串中相邻单词间有多个间隔符时,倒排转换后也只允许出现一个空格间隔符;

4、每个单词最长20个字母;

第一种方法

思路解析

  • 1.我们可以采用正则表达式把字符串分隔成为字符串数组

  • 2.接着我们再倒序输出字符串数组

  • 3.在注意最后一个字符串数组,可能是空格

public class ReverseStr2 {

public static void main(String args[]) {

Scanner sc = new Scanner(System.in);

while (sc.hasNext()) {

String str = sc.nextLine();

String[] strArray = str.split(“[^a-zA-Z]+”);

for (int i = strArray.length - 1; i >= 2; i–) {

System.out.print(strArray[i] + ’ ');

}

// 如果字符串数组的第一个元素是空串,那么下标为1的元素就是最后一个要输出的元素,末尾不要再加空格

if (strArray[0].length() == 0)

System.out.println(strArray[1]);

else

System.out.println(strArray[1] + ’ ’ + strArray[0]);

}

}

}

第二种方法

思路解析

  • 对输入的字符串进行分析,去掉非法字符,如中文字符,多个空格只保留一个空格等

  • 对字符串进行分组

  • 倒序输出

代码如下

/**

  • Created by xujun on 2016/9/20

*/

public class ReverseStr {

public static void main(String[] args) {

Scanner sc = new Scanner(System.in);

while (sc.hasNext()) {

StringBuilder sb = new StringBuilder();

String[] a = filter(sc.nextLine()).split(" ");

sb.append(a[a.length - 1]);

for (int i = a.length - 2; i >= 0; i–) {

sb.append(" " + a[i]);

}

System.out.println(sb.toString().trim());

}

}

public static String filter(String s) {

char[] c = s.toCharArray();

StringBuilder sb = new StringBuilder();

boolean isFirstSpace=true;

for (int i = 0; i < c.length; i++) {

if ((c[i] >= ‘a’ && c[i] <= ‘z’) || (c[i] >= ‘A’ && c[i] <= ‘Z’)) {

sb.append(c[i]);

isFirstSpace=true;

continue;

}

if(isFirstSpace){

sb.append(’ ');

isFirstSpace=false;

}

}

return sb.toString();

}

}


字符串全排列


思路分析

可以采用递归的形式

  • 从集合中依次选出每一个元素,作为排列的第一个元素,然后对剩余的元素进行全排列,如此递归处理,

  • 从而得到所有元素的全排列。以对字符串abc进行全排列为例,我们可以这么做:以abc为例:

  • 固定a,求后面bc的排列:abc,acb,求好后,a和b交换,得到bac

  • 固定b,求后面ac的排列:bac,bca,求好后,c放到第一位置,得到cba

  • 固定c,求后面ba的排列:cba,cab。

public class permutate {

public static int total = 0;

public static void swap(String[] str, int i, int j)

{

String temp = new String();

temp = str[i];

str[i] = str[j];

str[j] = temp;

}

public static void arrange (String[] str, int st, int len)

{

if (st == len - 1)

{

for (int i = 0; i < len; i ++)

{

System.out.print(str[i]+ " ");

}

System.out.println();

total++;

}

else

{

for (int i = st; i < len; i ++)

{

swap(str, st, i);

arrange(str, st + 1, len);

swap(str, st, i);

}

}

}

/**

  • @param args

*/

public static void main(String[] args) {

// TODO Auto-generated method stub

String str[] = {“a”,“b”,“c”};

arrange(str, 0, str.length);

System.out.println(total);

}

}

运行以上代码,将可以看到以下输出

a b c d

a b d c

a c b d

a c d b

a d c b

a d b c

b a c d

b a d c

b c a d

b c d a

b d c a

b d a c

c b a d

c b d a

c a b d

c a d b

c d a b

c d b a

d b c a

d b a c

d c b a

d c a b

d a c b

d a b c

24


全组合


第一种方法

思路解析

基本思路:求全组合,则假设原有元素n个,则最终组合结果是2^n个。

原因是: 用位操作方法:假设元素原本有:a,b,c三个,则1表示取该元素,0表示不取。故去a则是001,取ab则是011.所以一共三位,每个位上有两个选择0,1.所以是2^n个结果。

这些结果的位图值都是0,1,2…2n。所以可以类似全真表一样,从值0到值2n依次输出结果:即:

000,001,010,011,100,101,110,111

对应输出组合结果为:

空,a, b ,ab,c,ac,bc,abc.

这个输出顺序刚好跟数字0~2n结果递增顺序一样,取法的二进制数其实就是从0到2n-1的十进制数

public static void Combination( ) {

/*基本思路:求全组合,则假设原有元素n个,则最终组合结果是2^n个。原因是:

  • 用位操作方法:假设元素原本有:a,b,c三个,则1表示取该元素,0表示不取。故去a则是001,取ab则是011.

  • 所以一共三位,每个位上有两个选择0,1.所以是2^n个结果。

  • 这些结果的位图值都是0,1,2…2n。所以可以类似全真表一样,从值0到值2n依次输出结果:即:

  • 000,001,010,011,100,101,110,111 。对应输出组合结果为:

空,a, b ,ab,c,ac,bc,abc.

这个输出顺序刚好跟数字0~2^n结果递增顺序一样

取法的二进制数其实就是从0到2^n-1的十进制数


  • */

String[] str = {“a” , “b” ,“c”};

int n = str.length; //元素个数。

//求出位图全组合的结果个数:2^n

int nbit = 1<<n; // “<<” 表示 左移:各二进位全部左移若干位,高位丢弃,低位补0。:即求出2^n=2Bit。

System.out.println(“全组合结果个数为:”+nbit);

for(int i=0 ;i<nbit ; i++) { //结果有nbit个。输出结果从数字小到大输出:即输出0,1,2,3,…2^n。

System.out.print("组合数值 "+i + " 对应编码为: ");

for(int j=0; j<n ; j++) { //每个数二进制最多可以左移n次,即遍历完所有可能的变化新二进制数值了

int tmp = 1<<j ;

if((tmp & i)!=0) { //& 表示与。两个位都为1时,结果才为1

System.out.print(str[j]);

}

}

System.out.println();

}

}

第二种方法

Android高级架构师

由于篇幅问题,我呢也将自己当前所在技术领域的各项知识点、工具、框架等汇总成一份技术路线图,还有一些架构进阶视频、全套学习PDF文件、面试文档、源码笔记。

  • 330页PDF Android学习核心笔记(内含上面8大板块)

  • Android学习的系统对应视频

  • Android进阶的系统对应学习资料

  • Android BAT部分大厂面试题(有解析)

好了,以上便是今天的分享,希望为各位朋友后续的学习提供方便。觉得内容不错,也欢迎多多分享给身边的朋友哈。
《Android学习笔记总结+移动架构视频+大厂面试真题+项目实战源码》点击传送门,即可获取!
) { //& 表示与。两个位都为1时,结果才为1

System.out.print(str[j]);

}

}

System.out.println();

}

}

第二种方法

Android高级架构师

由于篇幅问题,我呢也将自己当前所在技术领域的各项知识点、工具、框架等汇总成一份技术路线图,还有一些架构进阶视频、全套学习PDF文件、面试文档、源码笔记。

  • 330页PDF Android学习核心笔记(内含上面8大板块)

[外链图片转存中…(img-LhX8vIL2-1715122630036)]

[外链图片转存中…(img-eD5qusv3-1715122630037)]

  • Android学习的系统对应视频

  • Android进阶的系统对应学习资料

[外链图片转存中…(img-2lBfbGcW-1715122630038)]

  • Android BAT部分大厂面试题(有解析)

[外链图片转存中…(img-frjAXcrh-1715122630039)]

好了,以上便是今天的分享,希望为各位朋友后续的学习提供方便。觉得内容不错,也欢迎多多分享给身边的朋友哈。
《Android学习笔记总结+移动架构视频+大厂面试真题+项目实战源码》点击传送门,即可获取!

  • 23
    点赞
  • 28
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值