博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
我的面试准备过程---字符串相关(更新中)
阅读量:5937 次
发布时间:2019-06-19

本文共 4289 字,大约阅读时间需要 14 分钟。

字符串简介

String 内置类型,不可理性,要更改的话考虑转StringBuffer,StringBuilder,char[]之类

对java来说,一个char的范围 [0,65535],16位

面试题总体分析

  • 和数组相关,内容广泛

    • 概念理解:字典序,哪个排在字典前面,哪个字典序就小

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

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

    • 数字运算(套数加法、二进制加法)

    • 排序、交换(partition过程)

    • 字符计数(hash): 变位词

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

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

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

例1 把一个0-1串进行排序,可以交换任意两个位置,问最少交换的次数

思路:快排partition 最左边0和最右边的1都可以不管

public int exchangeTimes(String s){        int answer = 0;        for(int i = 0, j = s.length() - 1; i < j; i++, j--){            for(; i < j && s.charAt(i) == '0'; i++);            for(; i < j && s.charAt(j) == '1'; j--);            if(i < j) answer++;        }        return answer;    }

例2 删除一个字符串所有的a,并且复制所有的b.注:字符数组足够大

public void solve(char[] chars){        //先删除a,可以利用原来字符串的空间,过程类似插入排序        int n = 0;//删除a后的字符数组长度        int bCount = 0;        for(int i = 0; s[i] != '\0'; i++){            if(chars[i] == 'a'){                chars[n++] = chars[i];            }            if(chars[i] == 'b'){                bCount++;            }        }        //从后往前复制        //步骤1. 遍历计算新串长度,b出现的次数2. 从后往前遍历 3.旧串复制,如果遇到b,复制两遍        int newLength = n + bCount;        chars[newLength] = '\0';      for(int i = n, j = newLength - 1; i >= 0; i--){            chars[j--] = chars[i];            if(chars[i] == 'b'){                chars[j--] = 'b';         }    }

思考题:如何把字符串的空格变成"%20"

public void replaceSpace(char[] chars){        int length = 0;        int spaceCount = 0;        for(int i = 0; chars[i] != '\0'; i++){            length++;            if(chars[i] == ' '){                spaceCount++;            }        }        int newLength = length + 2 * spaceCount;        chars[newLength] = '\0';        for(int i = newLength - 1, j = length; j >= 0; j--){            if(chars[j] == ' '){                char[i] = '0';                char[--i] = '2';                char[--i] = '%';             }else{                char[i--] = char[j];            }        }    }

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

方法1 快排partition,因为过程不稳定,所以数字相对顺序会变化

public void sortStar(char[] chars){        for(int i = 0 , j = 0; j < a.length; j++){            if(chars[i] == '*'){                swap(a[i++], a[j])            }        }    }    private void swap(char[] chars, int i, int j){        char temp = chars[i];        chars[i] = chars[j];        chars[j] = temp;    }

方法2 倒着处理

public void sortStar(char[] chars){        int length = chars.length;        int i = length - 1;        for(int j = length - 1; j >= 0; j--){            if(chars[j] != '*'){                chars[i--] = chars[j];            }        }        while(i >= 0){            chars[i--] = '*';        }    }

注意:以上两种解法的异同,方法1,用到交换和快排partition思想,但是无法保证数字的顺序;方法2,使用倒着向前处理的思想,如果必须用交换,只能采用方法1

例4 单词翻转

翻转句子中全部的单词,单词内容不变,例如I'm a student. 变为student. a I'm思路:in-place翻转 字符串第i位到第j位
while(i < j) swap(s[i++], s[j--]);
1. 翻转整个句子:.tneduts a m'I2. 每个单词单独翻转: students. a I'm这段代码写得非常丑陋
public void revertStr(char[] chars){    int length = chars.length;    //翻转整个句子    revertInPlace(chars, 0, length - 1);    //翻转每个单词    String str = new String(chars);    String[] strs = str.split(" ");    int wordCounts = strs.length;    int[] eachLength = new int[wordCounts];    int i = 0;    for(String s : strs){        eachLength[i++] = s.length();    }    int start = 0;    for(int j = 0; j < wordCounts; j++){        revertInPlace(chars, start, start + eachLength[j] - 1);        start += eachLength[j] + 1;    }}private void revertInPlace(char[] chars, int i, int j){    while(i < j){        swap(chars, i++, j--);    }}private void swap(char[] chars, int i, int j){    char temp = chars[i];    chars[i] = chars[j];    chars[j] = temp;}

思考题:字符串循环移位

abcd 移动1次为bcda,移动两次为cdab,移动三次为dabc结论:长度为n,移动m次,相当于移动m%n次    - 前m%n位翻转,后n-m%n位翻转    - 总体再翻转一次
public void circularMove(char[] chars, int m){    int n = chars.length;    revertInPlace(chars, 0, m % n - 1);    revertInPlace(chars, m % n, n - 1);    revertInPlace(chars, 0, n - 1);}private void revertInPlace(char[] chars, int i, int j){    while(i < j){        swap(chars, i++, j--);    }}private void swap(char[] chars, int i, int j){    char temp = chars[i];    chars[i] = chars[j];    chars[j] = temp;}

总结:

  • in-place(原地)理解

    • 本身为O(1)空间

    • 递归,堆栈空间可以不考虑

  • 原地相关的问题

    • 字符串循环左移、右移

    • 快排partition相关

  • 滑动窗口

    • 能达到O(n)的时间复杂度

    • O(1)的空间复杂度

  • 规则相关---细致

  • 匹配(暴力):KMP比较少见

  • Manacher----要求比较高的笔试

转载地址:http://bcttx.baihongyu.com/

你可能感兴趣的文章
洛谷P1108 低价购买 (最长下降子序列方案数)(int,long long等 范围)
查看>>
大道至简-第五章-心得体会
查看>>
Python编程从入门到实践,个人笔记
查看>>
哈尔滨理工大学第七届程序设计竞赛初赛(高年级组)F - 苦逼的单身狗
查看>>
oracle数据迁移
查看>>
ArchLinux and LXDE and LXDM
查看>>
对拍--from Altf4
查看>>
JavaScript基础6——全选示例
查看>>
JavaScript基础知识总结(三)
查看>>
【python3】爬取简书评论生成词云
查看>>
HttpApplication、HttpContext、HttpModule、HttpHandler
查看>>
Android Service学习
查看>>
【数据库】sql2008卸载和默认实例的删除 ...
查看>>
SDNU 1086.迷宫问题(bfs标记路径)
查看>>
类的高内聚低耦合
查看>>
怎么下载geventwebsocket
查看>>
React文档(十六)refs和DOM
查看>>
电信计费业务:预后融合OCS到底应该实扣还是虚扣?
查看>>
【算法学习笔记】42.正反DP 填充问题 SJTU OJ 1285 时晴时雨
查看>>
《Python编程从入门到实践》学习笔记<7>:用户输入和while循环
查看>>