字符串经典算法题

注意:java中String内置类型,不可更改,要更改的话可考虑转StringBuffer, StringBuilder, char []之类

          字符范围:[0,65535]

例1【0-1交换】

把一个0-1串(只包含0和1的串)进行排序,你可以交换任意两个位置,问最少交换的次数?

解析:利用快速排序的partition过程

public class Main {
    public static int f(String s){
        int sum = 0;
       char[]c = s.toCharArray();
       int low = 0,high = c.length-1;
       while(low<high){
           while(low<high && c[low]=='0')
               low++;
           while(low<high && c[high]=='1')
               high--;
           if(low<high){
               sum++;low++;high--;
           }
       }
       return sum;
    }
    public static void main(String[] args) {
        Scanner sc = new Scanner(System.in);
        String s = sc.nextLine().trim();
        System.out.println(f(s));
    }
}

例2【交换星号】

一个字符串只包含*和数字,请把它的*号都放开头。

方法一:快排的patition过程(数字的相对位置会发生变化)

 public static String f(String s){
        char []c = s.toCharArray();
        for(int i=0,j=0;j<c.length;j++){
            if(c[j]=='*') {
                c[j] = c[i];
                c[i] = '*';
                i++;
            }
        }
        return String.valueOf(c);
    }

方法二:倒着复制(数字的相对位置不发生改变)

 public static String f(String s){
        char []c = s.toCharArray();
        int j=c.length-1;
        for(int i=c.length-1;i>=0;i--){
            if(c[i]!='*') {
                c[j] = c[i];
                j--;
            }
        }
        while(j>=0){
            c[j]='*';j--;
        }
        return String.valueOf(c);
    }

例3【子串变位词】

给定两个串a和b,问b是否是a的子串的变位词。例如输入a = hello, b = lel, lle, ello都是true,但是b = elo是false。

解析:利用滑动窗口的思想

              a. 比如b的长度是3,则考察a[0..2], [1..3],[2..4]是否和b是变位词

              b.如何比较?用b中的次数减去a中一个“窗口”内的字符种类,如果结果全是0,则找到这样的子串了

              c.窗口如何滑动? 向右移动一位 新窗口a[i - lenb + 1..i]  旧窗口a[i – lenb.. i – 1] =》扔掉a[i – lenb] 加入a[i]

 public static Boolean f(String s,String son){
        int nonZero = 0;
        char[]a = s.toCharArray();
        char[]b = son.toCharArray();
        int []x = new int[26];//统计son中各字符数量
        for(int i=0;i<b.length;i++){
            if(++x[b[i]-'a']==1)
                nonZero++;
        }
        //第一个窗口[0,b.length-1]
        for(int i=0;i<b.length;i++){
           int m = a[i] - 'a';
           x[m]--;
           if(x[m]==0) nonZero--;
           else if(x[m]==-1) nonZero++;
        }
        if(nonZero==0) return true;
        /*新窗口a[i-lenb+1,i]
          旧窗口a[i-lenb,i-1]*/
        for(int i=b.length;i<a.length;i++){
            int m = a[i-b.length] - 'a';
            x[m]++;
            if(x[m]==1) nonZero++;
            else if(x[m]==0) nonZero--;
            m = a[i] - 'a';
            x[m]--;
            if(x[m]==0) nonZero--;
            else if(x[m]==-1) nonZero++;
            if(nonZero==0) return true;
        }
        return false;
    }

例4【单词翻转】

翻转句子中全部的单词,单词内容不变。 例如I’m a student.  变为student. a I’m

解析:先翻转整个句子,再每个单词单独翻转 

 static String f(String s){
        String result = "";
        String ns = reverse(s);
        String [] a = ns.split(" +");
        for(int i=0;i<a.length;i++){
            result += reverse(a[i])+" ";
        }
        return result.trim();
    }
    static String reverse(String s){
        char[]a = s.toCharArray();
        int low = 0,high = a.length-1;
        while(low<high){
            char c = a[low];
            a[low] = a[high];
            a[high] = c;
            low++;high--;
        }
        return String.valueOf(a);
    }

思考题:字符串循环移位abcd

移动1次变为bcda    移动2次变为cdab    移动3次变为dabc

结论: 长度为n, 移动m次,相当于移动m % n次 :前m % n位翻转,后n – m % n位翻转,总体再翻转一次

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值