算法(二)、字符串中的算法


一、String、StringBuffer、StringBuilder

(一)、String API

    String 类代表字符串。Java 程序中的所有字符串字面值(如 "abc" )都作为此类的实例实现。字符串是常量;它们的值在创建之后不能更改。字符串缓冲区支持可变的字符串。因为 String 对象是不可变的,所以可以共享。例如:

     String str = "abc";

等效于:

     char data[] = {'a', 'b', 'c'};
     String str = new String(data);

下面给出了一些如何使用字符串的更多示例:

     System.out.println("abc");
     String cde = "cde";
     System.out.println("abc" + cde);
     String c = "abc".substring(2,3);
     String d = cde.substring(1, 2);

    String 类包括的方法可用于检查序列的单个字符、比较字符串、搜索字符串、提取子字符串、创建字符串副本并将所有字符全部转换为大写或小写。大小写映射基于 Character 类指定的 Unicode 标准版。

Java 语言提供对字符串串联符号("+")以及将其他对象转换为字符串的特殊支持。字符串串联是通过 StringBuilder(或 StringBuffer)类及其 append 方法实现的字符串转换是通过 toString 方法实现的,该方法由 Object 类定义,并可被 Java 中的所有类继承。有关字符串串联和转换的更多信息,请参阅 Gosling、Joy 和 Steele 合著的 The Java Language Specification。除非另行说明,否则将 null 参数传递给此类中的构造方法或方法将抛出 NullPointerException。  


  1. String trim()

  2. int indexOf(String str)

    int indexOf(String str,int fromIndex)

  3. String toUpperCase()

  4. String toLowerCase()

  5. String substring(int beginIndex,int endIndex)

  6. boolean startswith(String prefix)

  7. boolean endwith(String suffix)

  8. String concat(String str)

  9. String split(String regex)

  10. int length()

  11. boolean isEmpty()

  12. byte[] getBytes()

  13. char[] toCharArray()

  14. String replace(char oldChar,char newChar)

  15. String replaceAll(String regex,String replacement)

  16. char charAt(int index)


(二)、StringBuffer API

    线程安全的可变字符序列。一个类似于 String 的字符串缓冲区,但不能修改。虽然在任意时间点上它都包含某种特定的字符序列,但通过某些方法调用可以改变该序列的长度和内容。

可将字符串缓冲区安全地用于多个线程。可以在必要时对这些方法进行同步,因此任意特定实例上的所有操作就好像是以串行顺序发生的,该顺序与所涉及的每个线程进行的方法调用顺序一致。

StringBuffer 上的主要操作是 append 和 insert 方法,可重载这些方法,以接受任意类型的数据。每个方法都能有效地将给定的数据转换成字符串,然后将该字符串的字符添加或插入到字符串缓冲区中。append 方法始终将这些字符添加到缓冲区的末端;而 insert 方法则在指定的点添加字符。 

  1. StringBuffer append()

  2. StringBuffer reverse()

  3. StringBuffer replace(int start, int end, String str)  

  4. int length()

  5. StringBuffer delete(int start,int end) 

  6. String toString()



(三)、StringBulider API

  一个可变的字符序列。此类提供一个与一个可变的字符序列。此类提供一个与 StringBuffer 兼容的 API,但不保证同步。该类被设计用作 StringBuffer 的一个简易替换,用在字符串缓冲区被单个线程使用的时候(这种情况很普遍)。如果可能,建议优先采用该类,因为在大多数实现中,它比 StringBuffer 要快

    在 StringBuilder 上的主要操作是 append 和 insert 方法,可重载这些方法,以接受任意类型的数据。每个方法都能有效地将给定的数据转换成字符串,然后将该字符串的字符添加或插入到字符串生成器中。append 方法始终将这些字符添加到生成器的末端;而 insert 方法则在指定的点添加字符。 

  1. StringBuffer append()

  2. StringBuffer reverse()

  3. StringBuffer replace(int start, int end, String str)  

  4. int length()

  5. StringBuffer delete(int start,int end) 

  6. String toString()


二、



1、统计一个字符串中每个字符出现的次数


方法一:使用map的key记录字符串中的字符,map的value记录key出现的次数


public class StringCount{
    public static void main(String args[]){
        String abc="";
        Map<Character,Integer> map = new HashMap<Character,Integer>();
        for(int i = 0;i<abc.length();i++){
            if(map.get(abc.charAt(0))!=null){
                map.put(abc.charAt(i),1);
            }else{
                map.put(abc.charAt(i),map.get(abc.charAt(i))+1);     
        }
    }
}



方法二:


2、字符串全排列

  输入为{‘a’,’b’,’c’},则其全排列组合为abc,acb,bac,bca,cba,cab


package cn.qiuuuu;
public class RecursionTree {
    public static void main(String[] args) {
        char[] s = { 'a', 'b', 'c' };
        pre(s, 0, 2);
    }
    public static void pre(char[] s, int from, int to) {
        if (from == to) {
            System.out.println(s);
        } else {
            for (int i = from; i <= to; i++) {
                swap(s, i, from);
                pre(s, from + 1, to);
                swap(s, from, i);
            }
        }
    }
    public static void swap(char[] s, int i, int j) {
        char tmp = s[i];
        s[i] = s[j];
        s[j] = tmp;
    }
}


19、输入一行字符,分别统计出其中英文字母、空格、数字和其它字符的个数。  

int a = 0, b = 0, c = 0, d = 0;
char[] ch = null;
Scanner sc = new Scanner(System.in);
String line = sc.nextLine();
System.out.println(line);
ch = line.toCharArray();
for (int i = 0; i < ch.length; i++) {
    if (ch[i] >= '0' && ch[i] <= '9') {
        a++;
    } else if (ch[i] >= 'a' && ch[i] <= 'z' || ch[i] >= 'A' && ch[i] <= 'Z') {
        b++;
    } else if (ch[i] == ' ') {
        c++;
    } else {
        d++;
    }
}
System.out.println(a + "," + b + "," + c + "," + d);


3、给定一个英文字符串,请写一段代码找出这个字符串中首先出现三次的那个英文字符(需要区分大小写)。

输入sdafdsfdfdfdddss,输出d


法一:

package com.analysys;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
public class Test04 {
    public static void main(String[] args) throws IOException {
        BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
        String str = br.readLine();
        char ch[] = str.toCharArray();
        int hash[] = new int[128];
        for (int i = 0; i < str.length(); i++) {
            if (ch[i] >= 'a' && ch[i] <= 'z' || ch[i] >= 'A' && ch[i] <= 'Z') {
                hash[ch[i]]++;
                if (hash[ch[i]] == 3) {
                    System.out.println(ch[i]);
                    break;
                }
            }
        }
    }
}


法二:

String str1 = "slkdjfsdjfdsdjfkjfdjfdk";
Map<Character, Integer> map = new HashMap<Character, Integer>();
for (int i = 0; i < str1.length(); i++) {
    if (map.get(str1.charAt(i)) == null) {
        map.put(str1.charAt(i), 1);
    } else {
        map.put(str1.charAt(i), map.get(str1.charAt(i)) + 1);
    }
    if (map.get(str1.charAt(i)) == 3) {
        System.out.println(str1.charAt(i));
        return;
    }
}






6、实现字符串反转

    输入"abcdefg",输出"gfedcba"

法一:

String str = "abcdefg";
StringBuffer sb = new StringBuffer(str);
sb.reverse();
System.out.println(sb);


7、实现字符串中的单词反转,每个单词内部的字符不改变

    输入"abc def gh i",输出"i gh def abc"

public static String reverse(String into) {
    StringBuffer s = new StringBuffer();
    String[] inn = into.split(" ");
    for (int i = inn.length - 1; i >= 0; i--) {
        if (i == 0) {
            s.append(inn[i]);
        } else {
            s.append(inn[i] + " ");
        }
    }
    return s.toString();
}


8、输入一个由数字组成的字符串,把它转换成整数并输出。例如:输入字符串"123",输出整数123。



9、判断两个字符串是否相同


String a = "abcddefg";
String b = "abcdefg";
byte[] aa = a.getBytes();
byte[] bb = b.getBytes();
Arrays.sort(aa);
Arrays.sort(bb);
a = new String(aa);
b = new String(bb);
if (a.equals(b)) {
    System.out.println("equal");
} else {
    System.out.println("not equsl");
}

法二:

String str = "abcdefg";
String strtemp = "";
for (int i = str.length() - 1; i >= 0; i--) {
    strtemp += str.charAt(i) + "";
}
System.out.println(strtemp);


10、判断一个字符串是否为回文


// 判断字符串是否为回文
// 法一
String str1 = "aaaf";
StringBuffer sb1 = new StringBuffer(str1);
sb1.reverse();
if (sb1.toString().equals(str1)) {
    System.out.println("是回文");
} else {
    System.out.println("不是回文");
}


// 法二

char[] c = str1.toCharArray();
for (int i = 0; i < c.length / 2; i++) {
    if (c[i] != c[c.length - i - 1]) {
        System.out.println("不是回文");
        return;
    }
}



11、删除字符串中重复的字符


12、计算字符串str1中出现str2的次数(子串出现的次数)


public static void maxCount(String str1, String str2) {
    int count = 0;
    for (int i = 0; i < str1.length(); i++) {
        int n = str1.indexOf(str2, i);
        if (n != -1) {
            i = n + 1;
            count++;
        }
    }
    System.out.println(count);
}


13、计算字符串中子串出现的次数




14、最长公共子序列(动态规划)


7788.png


random
a0
111
11
n012
2
2
2
d012333
r112333
o112344
i112344
d112344


String str1="android";
String str2="random";
int[][] c=new int[str1.length()+1][str2.length()+1];
int tmp=0;
for(int i=0;i<=str1.length();i++){
    for(int j=0;j<=str2.length();j++){
        if(i==0||j==0){
            c[i][j]=0;
        }else if(str1.charAt(i-1)==str2.charAt(j-1)){
            c[i][j] = c[i-1][j-1]+1;
        }else{
            c[i][j]=Math.max(c[i-1][j],c[i][j-1]);
        }
        tmp = c[i][j];
    }
}
System.out.println(tmp);



15、最长公共子串(动态规划)


7799.png


public static int lcs1(String str1, String str2) {
    int len1 = str1.length();
    int len2 = str2.length();
    int result = 0; // 记录最长公共子串长度
    int c[][] = new int[len1 + 1][len2 + 1];
    for (int i = 0; i <= len1; i++) {
        for (int j = 0; j <= len2; j++) {
            if (i == 0 || j == 0) {
                c[i][j] = 0;
            } else if (str1.charAt(i - 1) == str2.charAt(j - 1)) {
                c[i][j] = c[i - 1][j - 1] + 1;
                result = Math.max(c[i][j], result);
            } else {
                c[i][j] = 0;
            }
        }
    }
    return result;
}

16、


17、有一个X*Y的网格,小团要在此网格上从左上角到右下角,只能走格点且只能向右或向下走。请设计一个算法,计算小团有多少种走法。给定两个正整数int x,int y,请返回小团的走法数目。(动态规划&&递归) 
输入描述: 输入包括一行,逗号隔开的两个正整数x和y,取值范围[1,10]。 
输出描述: 输出包括一行,为走法的数目。 
示例
输入

3 2 
输出

10


解法一:动态规划

     


public static int max(){
    int m=10;
    int n=10;
    int tmp=0;
    int i,j;
    int arr[][]=new int[m+1][n+1];
    for(i=0;i<m;i++){
        arr[0][i]=1;
    }
    for(j=0;j<n;j++){
        arr[j][0]=1;
    }
    for(i=1;i<m+1;i++){
        for(j=1;j<n+1;j++){
            arr[i][j]=arr[i-1][j]+arr[i][j-1];
            tmp=arr[i][j];
        }
    }
    return tmp;
}

解法二:递归

public static int d(int n,int m){
    if(n==0||m==0){
        return 1;
    }else{
        return d(n,m-1)+d(n-1,m);
    }
}


17、设有n个正整数,将它们联接成一排,组成一个最小的多位整数。

程序输入:n个数

程序输出:联接成的多位数      例如:

n=2时,2个整数32,321连接成的最小整数为:32132,

n=4时,4个整数55,31,312, 33 联接成的最小整数为:312313355

String[] s={"678","789"};
Arrays.sort(s);
System.out.println(s[0]+s[1]);
BufferedReader bf=new BufferedReader(new InputStreamReader(System.in));
while(true){
    String []strings=bf.readLine().split(" ");
    Arrays.sort(strings);
    StringBuffer sb=new StringBuffer();
    for(int i=strings.length-1;i>=0;i--){
        sb.append(strings[i]);
}
System.out.println(sb);


16、判断字符串是否为变形词:给定两个字符串str1和str2,如果str1和str2中出现的字符种类一样、并且每种字符出现的次数一样,那么str1与str2互为变形词。实现一个函数判断两个字符串是否为变形词。

public static boolean idDeformation(String str1, String str2) {
    if (str1 == null || str2 == null || str1.length() != str2.length()) {
        return false;
    }
    char[] c1 = str1.toCharArray();
    char[] c2 = str2.toCharArray();
    int[] map = new int[256];
    for (int i = 0; i < c1.length; i++) {
        map[c1[i]]++;
    }
    for (int j = 0; j < c2.length; j++) {
        if (map[c2[j]]-- < 0) {
            return false;
        }
    }
    return true;
}

 


17字符串中数字子串求和



18、输入两个字符串,从第一字符串中删除第二个字符串中所有的字符。例如,输入”They are students.”和”aeiou”,则删除之后的第一个字符串变成”Thy r stdnts.” 



18、去掉字符串中连续出现k个0的子串



19、判断两个字符串是否互为旋转词



20、将整数字符串转换成整数型

    str="123",返回123

    str="012",因为023不符合习惯,返回0

    str="2147483647",返回2147483647

    str="2147483648",溢出了,返回0

    str="-123",返回-123



        

    

    

    

21、替换字符串中连续出现的指定字符串


22、字符串的统计字符串


23、判断字符数组中是否所有的字符都只出现过一次


24、在有序但含有空的数组中查照字符串


25、字符串的调整与替换


26、反转字符串


27、数组中两个字符串的最小距离


28、添加最少字符串,使整个字符串都是回文字符串


29、括号字符串的有效性和最长有效长度


30、公式字符串求值


31、0左边必须有1的二进制字符串常量


32、找到字符串的最长无重复子串


33、找到被指的新类型字符


34、最小包含子串的长度


35、回文最少分割数


36、字符串匹配问题


37、        


17、小明在一次机密的场合中无意中看到自己所需要的信息。但他只能在一张标签的空白处记下这些信息,位置不够。于是他想了一种方法:对连续重复的部分用数字表示。没有连续重复的字符就不变。如ABBBCC,表示为AB3C2。

输入描述:输入的每行是一个有字母构成的字符串。
输出描述:输出是压缩后的字符串。
输入样例:
    3
    ABBBCC
    MMMN
    DDDFFF
    输出样例
    AB3C2
    M3N
    D3F3