01 如何实现字符串的反转
例如:“I love you"反转后"you love I”
思路:第一次对整个字符串中的字符进行反转,然后对每个单词进行反转
public void swap(char [] cArr,int begin,int end){
while (begin<end){
char tmp=cArr[begin];
cArr[begin]=cArr[end];
cArr[end]=tmp;
begin++;
end--;
}
}
public String swapWords(String s){
char[] cArr= s.toCharArray();
//对整个字符串进行字符反转操作
swap(cArr,0,cArr.length-1);
int begin=0;
//对每个单词进行字符反转操作
for (int i=1;i<cArr.length;i++){
if (Character.isSpace(cArr[i])){
swap(cArr,begin,i-1);
begin=i+1;
}
}
swap(cArr,begin,cArr.length-1);
return new String(cArr);
}
public static void main(String[] args) {
String s ="I Love You";
System.out.println(new Swap().swapWords(s));
}
02 如何判断两个字符串是否由相同的字符组成
问题描述:由相同的字符组成是指组成两个字符串的字符以及各个字符的个数是一样的。只是排列顺序不同而已,例如:“aaaabbc”与“abcbaaa” 就由相同的字符组成。
方法一:排序法
就是对两个字符串中的字符进行排序,比较两个排序后的字符串是否相等。若相等,则表明它们由相同的字符组成,否则,表明它们由不同的字符组成
public static void compare(String s1,String s2){
byte[] b1=s1.getBytes();
byte[] b2=s2.getBytes();
Arrays.sort(b1);
Arrays.sort(b2);
s1=new String(b1);
s2=new String(b2);
if (s1.equals(s2)){
System.out.println("两个字符串相等");
}else
System.out.println("两个字符串不相等");
}
public static void main(String[] args) {
String s1 ="aaaabbc";
String s2 ="bbcaaaa";
compare(s1,s2);
s1="abcddddd";
s2="abcddddb";
compare(s1,s2);
}
方法二:空间换时间
假设字符串中只是用ASCII字符,由于ASCII字符共有266个(对应的编码为0~255),在实现时可以通过申请大小为266的数组来记录各个字符出现的个数,并初始化为0,然后遍历第一个字符串,将字符串中字符对应的ASCII码值作为数组下标,把对应的元素加1,然后遍历第二个字符串,把数组中对应的元素值-1.如果最后数组中各个元素的值都为0,说明这两个字符串是右相同的字符组成;否则,说明这两个字符串是由不同的字符组成。
public static void compare1(String s1,String s2){
byte[] b1=s1.getBytes();
byte[] b2=s2.getBytes();
int[] bCount = new int[256];
for(int i=0;i<s1.length();i++){
bCount[b1[i]]++;
bCount[b2[i]]--;
}
for(int i:bCount){
if(i!=0) {
System.out.println("两个字符串不相等");
return;
}
}
System.out.println("两个字符串相等");
}
public static void main(String[] args) {
String s1 ="aaaabbc";
String s2 ="bbcaaaa";
compare1(s1,s2);
s1="abcddddd";
s2="abcddddb";
compare1(s1,s2);
}
03 如何删除字符串中重复的字符
方法一:蛮力法
把字符串看做一个字符数组,对它进行双重循环遍历,如果发现有重复的字符,就把字符置换成 ‘\0’,然后把所有‘\0’去掉
public static String removeDuplicate(String str){
char [] c=str.toCharArray();
int len=c.length;
for (int i=0;i<len;i++){
if (c[i]=='\0')
continue;
for (int j=i+1;j<len;j++){
if (c[j]=='\0')
continue;
//把重复的字符置为\0
if(c[i]==c[j])
c[j]='\0';
}
}
int l=0;
int b[]=new int[len];
for (int i=0;i<len;i++){
if (c[i]!='\0')
b[l++]=c[i];
}
return new String(b,0,l);
}
public static void main(String[] args) {
String str="good morning";
System.out.println(removeDuplicate(str));
}
方法二:空间换时间
public static String removeDuplicate1(String str){
char[] c=str.toCharArray();
int len =c.length;
int[] flags = new int [8];//只需要8个32bit的int,8*32=256bit
int i;
for( i=0;i<len;i++){
int index=(int)c[i]/32;
int shift=(int)c[i]%32;
if((flags[index]&(1<<shift))!=0)
c[i]='\0';
flags[index]|=(1<<shift);
}
int l=0;
int b[]=new int[len];
for (i=0;i<len;i++){
if (c[i]!='\0')
b[l++]=c[i];
}
return new String(b,0,len);
}
public static void main(String[] args) {
String str="good morning";
System.out.println(removeDuplicate1(str));
}
方法三:正则表达式
public static String reverse(String str){
StringBuffer sb= new StringBuffer(str);
sb=sb.reverse();
return sb.toString();
}
public static String removeDuplicate2(String str){
str=reverse(str);
str=str.replaceAll("(?s)(.)(?=.*\\1)","");
str=reverse(str);
return str;
}
public static void main(String[] args) {
String str="good morning";
System.out.println(removeDuplicate2(str));
}
04 如何统计一行字符中有多少个单词
public static int wordCount(String s){
int word=0;
int count=0;
for (int i=0;i<s.length();i++){
if (Character.isSpace(s.charAt(i)))
word=0;
else if (word==0){
word=1;
count++;
}
}
return count;
}
public static void main(String[] args) {
String str="I am SongChengZhi";
System.out.println(wordCount(str));
}
05 如何按要求但因数组的排列情况
问题描述:针对1、 2、 2、 3、 4、 5这6个数字,写一个函数,打印出所有不同的排列,例如:512234 、 215432等,要求4不能出现第三位,3和5不能相连
思路:可以把排列组合问题转换成熟悉的图遍历问题。可以把1、 2、 2、 3、 4、 5这6个点看做图的6个结点,对6个结点两两相连可以组成一个无向连通图,这6个数字对应的全排列等价于从这个图中各个结点出发深度遍历这个图所有可能路径所组成的数字集合。例如,从节点1出发的而所有遍历路径组成了以1开头的所有数字的组合。由于3和5不能相连,因此在构造图时使图中3和5对应的结点不连通就可以满足这个条件。对于4不能在第三位,可以在遍历结束后判断是否满足这个条件。
private int[] numbers=new int[]{1,2,2,3,4,5};
private int n=numbers.length;
//用来标记图中节点是否被遍历过
private boolean[] visited=new boolean[n];
//图的二维数组表示
private int[][]graph=new int[n][n];
//数字的组合
private String combination="";
public Set<String> getAllCombinations(){
//构造图
buildGraph();
//用来存放所有组合
Set<String> set=new HashSet();
//分别从不同的节点出发,深度遍历图
for (int i=0;i<n;i++){
this.depthFirstSearch(i,set);
}
return set;
}
private void buildGraph() {
for (int i=0;i<n;i++){
for (int j=0;j<n;j++){
if (i==j){
graph[i][j]=0;
}else {
graph[i][j]=1;
}
}
}
//确保在遍历事3与5是不可达的
graph[3][5]=0;
graph[5][3]=0;
}
//对树从节点start位置开始进行深度遍历
private void depthFirstSearch(int start, Set<String> set) {
visited[start]=true;
combination=combination+numbers[start];
if (combination.length()==n){
//4不出现在第三个位置
if (combination.indexOf("4")!=2)
set.add(combination);
}
for (int j=0;j<n;j++){
if (graph[start][j]==1&&visited[j]==false)
depthFirstSearch(j,set);
}
combination=combination.substring(0,combination.length()-1);
visited[start]=false;
}
public static void main(String[] args) {
AllCombinations all=new AllCombinations();
Set<String> set =all.getAllCombinations();
Iterator<String> it =set.iterator();
while (it.hasNext()){
String string =it.next();
System.out.println(string);
}
}
06 如何输出字符串的所有组合
问题描述:假设字符串中的所有字符都不重复,如何输出字符串的所有组合,例如:输入abc,输出a ,b ,c ,ab ,ac ,bc ,abc,共七种组合。
方法一:递归法
public static void combineRecursiveImpl(char[]c,int begin,int len,StringBuffer sb){
if (len==0){
System.out.print(sb+" ");
return;
}
if (begin==c.length){
return;
}
sb.append(c[begin]);
combineRecursiveImpl(c,begin+1,len-1,sb);
sb.deleteCharAt(sb.length()-1);
combineRecursiveImpl(c,begin+1,len,sb);
}
public static void main(String[] args) {
String s="abc";
char[] c=s.toCharArray();
StringBuffer sb = new StringBuffer("");
int len=c.length;
for (int i=1;i<=len;i++)
combineRecursiveImpl(c,0,i,sb);
}
方法二:构造二进制法
例如:001表示输出结果中不含字符a ,b 只含 c ,及输出结果为c ,而101 表示输出结果为ac。原题就是一个要求输出001到111 这2^n-1 个组合对应的字符串.
public static void Combine(char[] c){
if (c==null){
return;
}
int len=c.length;
boolean used[]=new boolean[len];
char cache[]=new char[len];
int result=len;
while (true){
int index=0;
while(used[index]){
used[index]=false;
++result;
if (++index==len)
return;
}
used[index]=true;
cache[--result]=c[index];
System.out.print(new String(cache).substring(result)+" ");
}
}
public static void main(String[] args) {
String s="abc";
char[] c=s.toCharArray();
Combine(c);
}