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);
}