導航:首頁 > 程序命令 > 程序員面試字元串演算法

程序員面試字元串演算法

發布時間:2022-11-16 09:35:59

① 面試演算法題:你的任務就是計算出長度為n的字元串(只包含『A』、『B』和『C』),有多少個是暗黑字元串。

程序肯定不是判斷一個字元串是純潔的還是黑暗的。從現有的題目描述看,程序和題目沒有關系。

題目是否不全?

java程序員面試的問題

java面試題大全-基礎方面Java基礎方面:
1、作用域public,private,protected,以及不寫時的區別
答:區別如下:
作用域 當前類 同一package 子孫類 其他package
public √ √ √ √
protected √ √ √ ×
friendly √ √ × ×
private √ × × ×
不寫時默認為friendly
2、Anonymous Inner Class (匿名內部類) 是否可以extends(繼承)其它類,是否可以implements(實現)interface(介面)
答:匿名的內部類是沒有名字的內部類。不能extends(繼承) 其它類,但一個內部類可以作為一個介面,由另一個內部類實現
3、Static Nested Class 和 Inner Class的不同
答:Nested Class (一般是C++的說法),Inner Class (一般是JAVA的說法)。Java內部類與C++嵌套類最大的不同就在於是否有指向外部的引用上。註: 靜態內部類(Inner Class)意味著1創建一個static內部類的對象,不需要一個外部類對象,2不能從一個static內部類的一個對象訪問一個外部類對象
4、&和&&的區別
答:&是位運算符,表示按位與運算,&&是邏輯運算符,表示邏輯與(and)
5、Collection 和 Collections的區別
答:Collection是集合類的上級介面,繼承與他的介面主要有Set 和List.
Collections是針對集合類的一個幫助類,他提供一系列靜態方法實現對各種集合的搜索、排序、線程安全化等操作
6、什麼時候用assert
答:assertion(斷言)在軟體開發中是一種常用的調試方式,很多開發語言中都支持這種機制。在實現中,assertion就是在程序中的一條語句,它對一個boolean表達式進行檢查,一個正確程序必須保證這個boolean表達式的值為true;如果該值為false,說明程序已經處於不正確的狀態下,系統將給出警告或退出。一般來說,assertion用於保證程序最基本、關鍵的正確性。assertion檢查通常在開發和測試時開啟。為了提高性能,在軟體發布後,assertion檢查通常是關閉的
7、String s = new String("xyz");創建了幾個String Object
答:兩個,一個字元對象,一個字元對象引用對象
8、Math.round(11.5)等於多少? Math.round(-11.5)等於多少
答: Math.round(11.5)==12;Math.round(-11.5)==-11;round方法返回與參數最接近的長整數,參數加1/2後求其floor
9、short s1 = 1; s1 = s1 + 1;有什麼錯? short s1 = 1; s1 += 1;有什麼錯
答:short s1 = 1; s1 = s1 + 1; (s1+1運算結果是int型,需要強制轉換類型)short s1 = 1; s1 += 1;(可以正確編譯
10、Java有沒有goto
答:java中的保留字,現在沒有在java中使用
11、數組有沒有length()這個方法? String有沒有length()這個方法
答:數組沒有length()這個方法,有length的屬性。String有有length()這個方法
12、Overload和Override的區別。Overloaded的方法是否可以改變返回值的類型
答:方法的重寫Overriding和重載Overloading是Java多態性的不同表現。重寫Overriding是父類與子類之間多態性的一種表現,重載Overloading是一個類中多態性的一種表現。如果在子類中定義某方法與其父類有相同的名稱和參數,我們說該方法被重寫 (Overriding)。子類的對象使用這個方法時,將調用子類中的定義,對它而言,父類中的定義如同被"屏蔽"了。如果在一個類中定義了多個同名的方法,它們或有不同的參數個數或有不同的參數類型,則稱為方法的重載(Overloading)。Overloaded的方法是可以改變返回值的類型
13、Set里的元素是不能重復的,那麼用什麼方法來區分重復與否呢? 是用==還是equals()? 它們有何區別
答:Set里的元素是不能重復的,那麼用iterator()方法來區分重復與否。equals()是判讀兩個Set是否相等
equals()和==方法決定引用值是否指向同一對象equals()在類中被覆蓋,為的是當兩個分離的對象的內容和類型相配的話,返回真值
14、給我一個你最常見到的runtime exception
答:常見的運行時異常有如下這些ArithmeticException, ArrayStoreException, BufferOverflowException, BufferUnderflowException, CannotRedoException, CannotUndoException, ClassCastException, CMMException, , DOMException, EmptyStackException, IllegalArgumentException, IllegalMonitorStateException, IllegalPathStateException, IllegalStateException, ImagingOpException, IndexOutOfBoundsException, MissingResourceException, NegativeArraySizeException, NoSuchElementException, NullPointerException, ProfileDataException, ProviderException, RasterFormatException, SecurityException, SystemException, UndeclaredThrowableException, UnmodifiableSetException, UnsupportedOperationException
15、error和exception有什麼區別
答:error 表示恢復不是不可能但很困難的情況下的一種嚴重問題。比如說內存溢出。不可能指望程序能處理這樣的情況
exception 表示一種設計或實現問題。也就是說,它表示如果程序運行正常,從不會發生的情況
16、List, Set, Map是否繼承自Collection介面
答: List,Set是,Map不是
17、abstract class和interface有什麼區別
答:聲明方法的存在而不去實現它的類被叫做抽象類(abstract class),它用於要創建一個體現某些基本行為的類,並為該類聲明方法,但不能在該類中實現該類的情況。不能創建abstract 類的實例。然而可以創建一個變數,其類型是一個抽象類,並讓它指向具體子類的一個實例。不能有抽象構造函數或抽象靜態方法。Abstract 類的子類為它們父類中的所有抽象方法提供實現,否則它們也是抽象類為。取而代之,在子類中實現該方法。知道其行為的其它類可以在類中實現這些方法
介面(interface)是抽象類的變體。在介面中,所有方法都是抽象的。多繼承性可通過實現這樣的介面而獲得。介面中的所有方法都是抽象的,沒有一個有程序體。介面只可以定義static final成員變數。介面的實現與子類相似,除了該實現類不能從介面定義中繼承行為。當類實現特殊介面時,它定義(即將程序體給予)所有這種介面的方法。然後,它可以在實現了該介面的類的任何對象上調用介面的方法。由於有抽象類,它允許使用介面名作為引用變數的類型。通常的動態聯編將生效。引用可以轉換到介面類型或從介面類型轉換,instanceof 運算符可以用來決定某對象的類是否實現了介面
18、abstract的method是否可同時是static,是否可同時是native,是否可同時是synchronized
答:都不能
19、介面是否可繼承介面? 抽象類是否可實現(implements)介面? 抽象類是否可繼承實體類(concrete class)
答:介面可以繼承介面。抽象類可以實現(implements)介面,抽象類是否可繼承實體類,但前提是實體類必須有明確的構造函數
20、構造器Constructor是否可被override
答:構造器Constructor不能被繼承,因此不能重寫Overriding,但可以被重載Overloading
21、是否可以繼承String類
答:String類是final類故不可以繼承
22、try {}里有一個return語句,那麼緊跟在這個try後的finally {}里的code會不會被執行,什麼時候被執行,在return前還是後
答:會執行,在return前執行
23、用最有效率的方法算出2乘以8等於幾
答:2 << 3
24、兩個對象值相同(x.equals(y) == true),但卻可有不同的hash code,這句話對不對
答:不對,有相同的hash code
25、當一個對象被當作參數傳遞到一個方法後,此方法可改變這個對象的屬性,並可返回變化後的結果,那麼這里到底是值傳遞還是引用傳遞
答:是值傳遞。Java 編程語言只有值傳遞參數。當一個對象實例作為一個參數被傳遞到方法中時,參數的值就是對該對象的引用。對象的內容可以在被調用的方法中改變,但對象的引用是永遠不會改變的
26、swtich是否能作用在byte上,是否能作用在long上,是否能作用在String上
答:witch(expr1)中,expr1是一個整數表達式。因此傳遞給 switch 和 case 語句的參數應該是 int、 short、 char 或者 byte。long,string 都不能作用於swtich
27、ArrayList和Vector的區別,HashMap和Hashtable的區別
答:就ArrayList與Vector主要從二方面來說.
一.同步性:Vector是線程安全的,也就是說是同步的,而ArrayList是線程序不安全的,不是同步的
二.數據增長:當需要增長時,Vector默認增長為原來一培,而ArrayList卻是原來的一半
就HashMap與HashTable主要從三方面來說。
一.歷史原因:Hashtable是基於陳舊的Dictionary類的,HashMap是Java 1.2引進的Map介面的一個實現
二.同步性:Hashtable是線程安全的,也就是說是同步的,而HashMap是線程序不安全的,不是同步的
三.值:只有HashMap可以讓你將空值作為一個表的條目的key或value
28、char型變數中能不能存貯一個中文漢字?為什麼?
答:是能夠定義成為一個中文的,因為java中以unicode編碼,一個char佔16個位元組,所以放一個中文是沒問題的
29、GC是什麼? 為什麼要有GC
答:GC是垃圾收集的意思(Gabage Collection),內存處理是編程人員容易出現問題的地方,忘記或者錯誤的內存回收會導致程序或系統的不穩定甚至崩潰,Java提供的GC功能可以自動監測對象是否超過作用域從而達到自動回收內存的目的,Java語言沒有提供釋放已分配內存的顯示操作方法。
30、float型float f=3.4是否正確?
答:不正確。精度不準確,應該用強制類型轉換,如下所示:float f=(float)3.4
31、介紹JAVA中的Collection FrameWork(包括如何寫自己的數據結構)?
答:Collection FrameWork如下:
Collection
├List
│├LinkedList
│├ArrayList
│└Vector
│└Stack
└Set
Map
├Hashtable
├HashMap
└WeakHashMap
Collection是最基本的集合介面,一個Collection代表一組Object,即Collection的元素(Elements)
Map提供key到value的映射
32、抽象類與介面?
答:抽象類與介面都用於抽象,但是抽象類(JAVA中)可以有自己的部分實現,而介面則完全是一個標識(同時有多重繼承的功能)。
JAVA類實現序例化的方法是實現java.io.Serializable介面
Collection框架中實現比較要實現Comparable 介面和 Comparator 介面
33、STRING與STRINGBUFFER的區別。
答:STRING的長度是不可變的,STRINGBUFFER的長度是可變的。如果你對字元串中的內容經常進行操作,特別是內容要修改時,那麼使用StringBuffer,如果最後需要String,那麼使用StringBuffer的toString()方法
34、談談final, finally, finalize的區別
答:final?修飾符(關鍵字)如果一個類被聲明為final,意味著它不能再派生出新的子類,不能作為父類被繼承。因此一個類不能既被聲明為 abstract的,又被聲明為final的。將變數或方法聲明為final,可以保證它們在使用中不被改變。被聲明為final的變數必須在聲明時給定初值,而在以後的引用中只能讀取,不可修改。被聲明為final的方法也同樣只能使用,不能重載
finally?再異常處理時提供 finally 塊來執行任何清除操作。如果拋出一個異常,那麼相匹配的 catch 子句就會執行,然後控制就會進入 finally 塊(如果有的話)
finalize?方法名。Java 技術允許使用 finalize() 方法在垃圾收集器將對象從內存中清除出去之前做必要的清理工作。這個方法是由垃圾收集器在確定這個對象沒有被引用時對這個對象調用的。它是在 Object 類中定義的,因此所有的類都繼承了它。子類覆蓋 finalize() 方法以整理系統資源或者執行其他清理工作。finalize() 方法是在垃圾收集器刪除對象之前對這個對象調用的
35、面向對象的特徵有哪些方面
答:主要有以下四方面:
1.抽象:
抽象就是忽略一個主題中與當前目標無關的那些方面,以便更充分地注意與當前目標有關的方面。抽象並不打算了解全部問題,而只是選擇其中的一部分,暫時不用部分細節。抽象包括兩個方面,一是過程抽象,二是數據抽象。
2.繼承:
繼承是一種聯結類的層次模型,並且允許和鼓勵類的重用,它提供了一種明確表述共性的方法。對象的一個新類可以從現有的類中派生,這個過程稱為類繼承。新類繼承了原始類的特性,新類稱為原始類的派生類(子類),而原始類稱為新類的基類(父類)。派生類可以從它的基類那裡繼承方法和實例變數,並且類可以修改或增加新的方法使之更適合特殊的需要。
3.封裝:
封裝是把過程和數據包圍起來,對數據的訪問只能通過已定義的界面。面向對象計算始於這個基本概念,即現實世界可以被描繪成一系列完全自治、封裝的對象,這些對象通過一個受保護的介面訪問其他對象。
4. 多態性:
多態性是指允許不同類的對象對同一消息作出響應。多態性包括參數化多態性和包含多態性。多態性語言具有靈活、抽象、行為共享、代碼共享的優勢,很好的解決了應用程序函數同名問題。
36、String是最基本的數據類型嗎
答:基本數據類型包括byte、int、char、long、float、double、boolean和short。
java.lang.String類是final類型的,因此不可以繼承這個類、不能修改這個類。為了提高效率節省空間,我們應該用StringBuffer類
37、int 和 Integer 有什麼區別
答:Java 提供兩種不同的類型:引用類型和原始類型(或內置類型)。Int是java的原始數據類型,Integer是java為int提供的封裝類。Java為每個原始類型提供了封裝類。
原始類型封裝類,booleanBoolean,charCharacter,byteByte,shortShort,intInteger,longLong,floatFloat,doubleDouble
引用類型和原始類型的行為完全不同,並且它們具有不同的語義。引用類型和原始類型具有不同的特徵和用法,它們包括:大小和速度問題,這種類型以哪種類型的數據結構存儲,當引用類型和原始類型用作某個類的實例數據時所指定的預設值。對象引用實例變數的預設值為 null,而原始類型實例變數的預設值與它們的類型有關
38、運行時異常與一般異常有何異同
答:異常表示程序運行過程中可能出現的非正常狀態,運行時異常表示虛擬機的通常操作中可能遇到的異常,是一種常見運行錯誤。java編譯器要求方法必須聲明拋出可能發生的非運行時異常,但是並不要求必須聲明拋出未被捕獲的運行時異常。
39、說出ArrayList,Vector, LinkedList的存儲性能和特性
答:ArrayList和Vector都是使用數組方式存儲數據,此數組元素數大於實際存儲的數據以便增加和插入元素,它們都允許直接按序號索引元素,但是插入元素要涉及數組元素移動等內存操作,所以索引數據快而插入數據慢,Vector由於使用了synchronized方法(線程安全),通常性能上較ArrayList差,而LinkedList使用雙向鏈表實現存儲,按序號索引數據需要進行前向或後向遍歷,但是插入數據時只需要記錄本項的前後項即可,所以插入速度較快。
40、HashMap和Hashtable的區別
答:HashMap是Hashtable的輕量級實現(非線程安全的實現),他們都完成了Map介面,主要區別在於HashMap允許空(null)鍵值(key),由於非線程安全,效率上可能高於Hashtable。
HashMap允許將null作為一個entry的key或者value,而Hashtable不允許。
HashMap把Hashtable的contains方法去掉了,改成containsvalue和containsKey。因為contains方法容易讓人引起誤解。
Hashtable繼承自Dictionary類,而HashMap是Java1.2引進的Map interface的一個實現。
最大的不同是,Hashtable的方法是Synchronize的,而HashMap不是,在多個線程訪問Hashtable時,不需要自己為它的方法實現同步,而HashMap 就必須為之提供外同步。
Hashtable和HashMap採用的hash/rehash演算法都大概一樣,所以性能不會有很大的差異。

③ c#面試題字元串分割問題

C#最簡單的分割你這樣的字串,用它本身的Split函數就可以了,這個是很基礎的了
但面試肯定不是那麼簡單的,它要考慮轉換成int數組,這個要用到使用Array類中的靜態泛形式方法ConvertAll進行轉換,這個是難點,參考程序如下:

string
s="1,2,,4";

string
[]x=s.Split(',');

int[]
output
=
Array.ConvertAll<string,
int>(x,
delegate(string
t)
{
return
int.Parse(t);
});

④ leetcode-程序員面試金典-字元串比較

看完之後,立刻根據三種情況開始處理.....

insert和delete都是使用的之前迴文序列的較為繁瑣的去重方法搞定的,bug來源就這里了。

也怪我沒怎麼好好理解題的意思,英文版的更好明白一點,只能是「one/zero edit」才能返回true,其他情況統統是false。
這樣的話對字元串的匹配程度應該要求很高,insert和delete的處理過於粗糙了。

然後測試不通過,看到用例我才傻眼了

這樣的情況下字元串完美匹配就非常重要了,因為從測試用例知道不能僅僅要求字元串的字元元素匹配,還得要求字元順序也匹配。

最後採用雙索引方法通過,用時2ms

⑤ java面試有哪些演算法

面試-java演算法題:
1.編寫一個程序,輸入n,求n!(用遞歸的方式實現)。
public static long fac(int n){ if(n<=0) return 0; else if(n==1) return 1; else return n*fac(n-1);
} public static void main(String [] args) {
System.out.println(fac(6));
}
2.編寫一個程序,有1,2,3,4個數字,能組成多少個互不相同且無重復數字的三位數?都是多少?
public static void main(String [] args) { int i, j, k; int m=0; for(i=1;i<=4;i++) for(j=1;j<=4;j++) for(k=1;k<=4;k++){ if(i!=j&&k!=j&&i!=k){
System.out.println(""+i+j+k);
m++;
}
}
System.out.println("能組成:"+m+"個");
}
3.編寫一個程序,將text1.txt文件中的單詞與text2.txt文件中的單詞交替合並到text3.txt文件中。text1.txt文件中的單詞用回車符分隔,text2.txt文件中用回車或空格進行分隔。
import java.io.File;
import java.io.FileReader;
import java.io.FileWriter;

public class text{
public static void main(String[] args) throws Exception{
String[] a = getArrayByFile("text1.txt",new char[]{'\n'});
String[] b = getArrayByFile("text2.txt",new char[]{'\n',' '});
FileWriter c = new FileWriter("text3.txt");
int aIndex=0; int bIndex=0;

while(aIndex<a.length){
c.write(a[aIndex++] + "\n");
if(bIndex<b.length)
c.write(b[bIndex++] + "\n");
}

while(bIndex<b.length){
c.write(b[bIndex++] + "\n");
}
c.close();
}

public static String[] getArrayByFile(String filename,char[] seperators) throws Exception{
File f = new File(filename);
FileReader reader = new FileReader(f);
char[] buf = new char[(int)f.length()];
int len = reader.read(buf);
String results = new String(buf,0,len);
String regex = null;
if(seperators.length >1 ){
regex = "" + seperators[0] + "|" + seperators[1];
}else{
regex = "" + seperators[0];
}
return results.split(regex);
}

}
4.639172每個位數上的數字都是不同的,且平方後所得數字的所有位數都不會出現組成它自身的數字。(639172*639172=408540845584),類似於639172這樣的6位數還有幾個?分別是什麼?
這題採用的HashMap結構判斷有無重復,也可以採用下題的數組判斷。
public void selectNum(){
for(long n = 100000; n <= 999999;n++){
if(isSelfRepeat(n)) //有相同的數字,則跳過
continue;
else if(isPingFangRepeat(n*n,n)){ //該數的平方中是否有與該數相同的數字
continue;
} else{ //符合條件,則列印 System.out.println(n);
}
}
} public boolean isSelfRepeat(long n){
HashMap<Long,String> m=new HashMap<Long,String>(); //存儲的時候判斷有無重復值
while(n!=0){ if(m.containsKey(n%10)){ return true;
} else{
m.put(n%10,"1");
}
n=n/10;
} return false;
} public boolean isPingFangRepeat(long pingfang,long n){
HashMap<Long,String> m=new HashMap<Long,String>(); while(n!=0){
m.put(n%10,"1");
n=n/10;
} while(pingfang!=0){ if(m.containsKey(pingfang%10)){ return true;
}
pingfang=pingfang/10;
} return false;
} public static void main(String args[]){ new test().selectNum();
}
5.比如,968548+968545=321732732它的答案里沒有前面兩個數里的數字,有多少這樣的6位數。
public void selectNum(){
for(int n = 10; n <= 99;n++){
for(int m = 10; m <= 99;m++){ if(isRepeat(n,m)){ continue;
} else{
System.out.println("組合是"+n+","+m);
}
}
}
} public boolean isRepeat(int n,int m){ int[] a={0,0,0,0,0,0,0,0,0,0}; int s=n+m; while(n!=0){
a[n%10]=1;
n=n/10;
} while(m!=0){
a[m%10]=1;
m=m/10;
} while(s!=0){ if(a[s%10]==1){ return true;
}
s=s/10;
} return false;
} public static void main(String args[]){ new test().selectNum();
}
6.給定String,求此字元串的單詞數量。字元串不包括標點,大寫字母。例如 String str="hello world hello hi";單詞數量為3,分別是:hello world hi。
public static void main(String [] args) { int count = 0;
String str="hello world hello hi";
String newStr="";
HashMap<String,String> m=new HashMap<String,String>();
String [] a=str.split(" "); for (int i=0;i<a.length;i++){ if(!m.containsKey(a[i])){
m.put(a[i],"1");
count++;
newStr=newStr+" "+a[i];
}
}
System.out.println("這段短文單詞的個數是:"+count+","+newStr);
}
7.寫出程序運行結果。
public class Test1 { private static void test(int[]arr) { for (int i = 0; i < arr.length; i++) { try { if (arr[i] % 2 == 0) { throw new NullPointerException();
} else {
System.out.print(i);
}
} catch (Exception e) {
System.out.print("a ");
} finally {
System.out.print("b ");
}
}
}
public static void main(String[]args) { try {
test(new int[] {0, 1, 2, 3, 4, 5});
} catch (Exception e) {
System.out.print("c ");
}
}

}
運行結果:a b 1b a b 3b a b 5b
public class Test1 { private static void test(int[]arr) { for (int i = 0; i < arr.length; i++) { try { if (arr[i] % 2 == 0) { throw new NullPointerException();
} else {
System.out.print(i);
}
}
finally {
System.out.print("b ");
}
}
}
public static void main(String[]args) { try {
test(new int[] {0, 1, 2, 3, 4, 5});
} catch (Exception e) {
System.out.print("c ");
}
}

}
運行結果:b c
8.單詞數
統計一篇文章里不同單詞的總數。
Input
有多組數據,每組一行,每組就是一篇小文章。每篇小文章都是由小寫字母和空格組成,沒有標點符號,遇到#時表示輸入結束。
Output
每組值輸出一個整數,其單獨成行,該整數代表一篇文章里不同單詞的總數。
Sample Input
you are my friend
#
Sample Output
4
public static void main(String [] args) {
List<Integer> countList=new ArrayList<Integer>(); int count;
HashMap<String,String> m;
String str; //讀取鍵盤輸入的一行(以回車換行為結束輸入) String[] a;

Scanner in=new Scanner(System.in);
while( !(str=in.nextLine()).equals("#") ){
a=str.split(" ");
m=new HashMap<String,String>();
count = 0; for (int i=0;i<a.length;i++){ if(!m.containsKey(a[i]) && (!a[i].equals(""))){
m.put(a[i],"1");
count++;
}
}
countList.add(count);
}s for(int c:countList)
System.out.println(c);
}

⑥ 尋找最大迴文字元串: Manacher演算法詳解

Manacher演算法是一種用於找出給定字元串中最長的迴文字元子串的演算法.該演算法的神來之筆是: 用一個不會出現在該目標字元串中的特殊字元對目標字元串進行填充, 為描述簡便, 我們就假設該特殊符號為"#", 並且演算法是從字元串的左端向右端開始尋找.

我們這樣來完成填充:

1)在目標字元串的每個字元前面都塞入一個"#";

2)在目標字元串的末端加一個"#".

如此一來, 任意字元串" *** "填充之後都會變成這個樣子" #*#*#*# "

從填充的兩個步驟可以看出, 任意長度為n的字元串, 在填充之後長度都會變成n+n+1, 即2n+1, 也就是說填充之後得到的字元串的長度一定是奇數.

由於後面不可避免地要討論字元的位置下標, 所以從這里開始, 我們就把被填充後的字元串看做一個字元數組, 如果被填充前的目標字元串長度為n, 那麼該字元數組的下標顯然就是從0開始, 到2n結束. 同時為了後續描述的統一和便於理解, 我們在這個字元數組的基礎上定義幾個代名詞:

當前有效迴文字元串 : 它是指當前已經找到的, 擁有 最大右端下標的迴文字元串 , 注意 , 它不一定是已經找到的最長迴文字元串.

mPoint : middle point, 它是指當前有效迴文字元串的 中點字元的下標 . mPoint的初始值是0, 它會逐漸右移.

radius : 迴文字元串半徑 , 由於迴文字元串是關於中點位置對稱的, 所以把長度為n的迴文字元串的半徑定義為從中點位置分割後, 任意一側的字元串長度+1(要把中點位置的字元算進去), 即n/2 + 1. 請注意: Manacher演算法第一步所做的填充, 其神奇之處在這里開始顯現, 因為從填充後的字元串中找出的最長迴文字元串的長度也一定是奇數, 並且 radius-1 就是原始字元串中迴文字元串的長度, 比如:

原字元串是"bbad", 我們可以找到的最長迴文字元串是長度為2(偶數)的"bb"

而由於填充之後的字元串是"#b#b#a#d#", 所以我們可以找到的最長迴文字元串就變成了長度為5(奇數)的"#b#b#" (半徑為3, 減1恰好等於2)

原字元串是"cabad", 我們可以找到的最長迴文字元串是長度為3(奇數)的"aba"

而由於填充之後的字元串是"#c#a#b#a#d#", 所以我們可以找到的最長迴文字元串就變成了長度為7(仍為奇數)的"#a#b#a#" (半徑為4, 減1恰好等於3)

數組P : 構造一個數組P, 用於記錄字元數組中每個元素以其為中點可以形成的最大迴文字元串的半徑

rPoint : right point, 它是指當前有效迴文字元串的右端字元的下標+1(注意我們是從左端開始檢查的), rPoint = mPoint+P[mPoint]. rPoint 的作用是利用迴文字元串的特性, 減少不必要的檢查, 後面會詳述. rPoint 的初始值是0, 它會逐漸右移

Manacher演算法開始:

第一步, 初始化:

令  i = 0 (當前檢查的字元下標), mPoint=0 , rPoint = 0

第二步:

判斷不等式① i < rPoint , 亦即確認當前檢查的字元是否落在了當前有效迴文字元串內

如果不等式①不成立, 說明當前還 沒有找到迴文字元串 , 或者 當前有效迴文字元串 的半徑 沒有覆蓋 到當前檢查的字元, 則令 radius = 1 開始檢查, 由於 radius = 1 , 即只包含當前元素本身, 必然立即找到以當前字元為中點第一個迴文字元串(即它自己), 更新 P[i] = 1

如果不等式①成立, 說明之前的檢查已經找到了 當前有效迴文字元串, 並且其半徑覆蓋到了當前檢查的字元,  也可以說當前檢查的字元落在了 當前有效迴文字元串內

那麼  i 一定有一個關於當前有效迴文字元串的中點即  mPoint  的 對稱點 , 我們稱它為  j

作為同在當前有效迴文字元串內的兩個對稱點, 在不超出當前有效迴文字元串的左右兩端的前提下, 注意這里要強調不超出 , 我們不難想像, 如果以  j  為中點可以形成一個迴文字元串, 那麼一定也可以以 i 為中點形成一個相同的迴文字元串(否則就不對稱, 當前有效迴文字元串就不可能存在).

於是我們可以整理下目前已經直接或者間接知道的事實:

(1) P[j] 中已經存儲了以 j 這個元素為中點可以形成的最長迴文字元串半徑

(2) 當前有效迴文字元串是以 mPoint 為中心可以形成的最長迴文字元串, 也就是說以 mPoint 為中心, 不可能再有更長的迴文字元串 , 並且其半徑已經存儲在了 P[mPoint] 中

(3) 如果迴文字元串內部 對稱 位置上有兩個迴文子串, 那麼這兩個迴文子串必然是相同的

進而我們可以有以下推導(請讀者不妨拿出筆和紙畫一畫線段圖, 幫助理解):

a. 當  P[j]>rPoint-i  時, 也就是說以 j 這個元素為中點形成的最長迴文字元串足以延伸至當前有效迴文字元串左端以外時, 則一定有 P[i] = rPoint-i , 因為如果 P[i] > rPoint-i , 說明以 i 這個元素為中點形成的最長迴文字元串足以延伸至當前有效迴文字元串右端以外, 那麼 當前有效迴文字元串 就應該有更長的半徑, 但這與事實(2)矛盾了. 而如果 P[i] < rPoint-i , 則在當前有效迴文字元串內部就會出現不對稱使其不能成為迴文字元串, 這同樣產生矛盾.

b. 當 P[j]<rPoint-i 時, 也就是說以 j 這個元素為中點形成的最長迴文字元串完全被包裹在 當前有效迴文字元串 內部時, 則一定有 P[i] = P[j] , 否則它與事實(3)矛盾

以上兩種情況就可以直接得出P[i], 無需任何檢查!

c. 當 P[j] = rPoint-i 時呢? 這時只能確定 P[i] 應至少等於 rPoint-i , 否則會與事實(3)矛盾, 可是 P[i] 可以更大, 這時我們才需要令 radius=rPoint-i 開始檢查(這就比令 radius = 1 開始檢查高效)

以當前元素為中點, 半徑為 radius 開始檢查迴文字元串, 如果是迴文字元串則擴展半徑 radius , 嘗試尋找更長的迴文字元串, 直至失敗

此時要滿足兩個條件:

②擴展半徑之後, 左端和右端的下標不越界.

③當前左端和右端的元素字元相同.

如果條件②和③都成立,則 P[i] = P[i] + 1

緊接著判斷不等式④ i+P[i] > rPoint

如果④成立, 說明當前迴文字元串的右端已經延伸到了更靠右的位置, 即產生新的 當前有效迴文字元串

立即更新 mPoint 為當前的 i , rPoint 為 i+P[i]

mPoint=i

rPoint=i+P[i]

如果 P[i] 比已知的最大迴文字元串半徑都大, 記錄並更新最大半徑(根據最終需求結果不同也可能是記錄 mPoint 和 rPoint 的下標), 

循環執行直至②或③不成立

第三步

i  自增, 重復執行第二步, 直至  i  到達字元數組的最有端(當然如果從  i  的位置不可能再找到比當前最長迴文字元串更長的迴文字元串時,   就可以提前結束)

⑦ 面試題 描述java中字元串的比較方式有哪些

java中的字元串比較方法:
1)string1.equals(string2)
2) str1==str2 。
java中字元串的比較是==比較引用,equals 比較值的做法。但是不同的聲明方法字元串的比較結果也是不同的。
例如: String str1=new String("a");
String str2=new String("a");
str1==str2 輸出false
str1.equals(str2) 輸出true
而如果這樣聲明
String str1="a";
String str2="a";
str1==str2 輸出true
str1.equals(str2) 輸出true
這是因為 equals 方法本來也是比較引用的字元串類在實現的時候重寫了該方法。
第一種聲明方法等於是聲明了兩個對象,用』==『比較是時候比較的是引用輸出的是false 由於他們的值相同用equals的時候就比較的是值了,輸出true。

第二種情況不是因為比較有與第一種有差異,而是因為聲明有差異,第二種聲明方法在聲明的時候有堆或堆棧 共用的現象,也就是說
在聲明的時候如果如果聲明為類屬性他會檢查在堆棧中有沒有與現在聲明的是相同結構的字元串。如果有就直接將地址指向已有內存地址。聲明在方法內部的局部變
量原理一樣只不過他是堆棧共享。

⑧ Java程序員面試題 1.String s = new String(「xyz」); 創建了幾個String Object

通常版
創建2個String 對象, 都為 "xyz".

嚴禁版
要看 外部條件, 在標准SUN JVM里, 如果在此代碼之前的代碼中有"xyz"的聲明 那麼只會創建 一個String 對象 即通過new 關鍵字創建出來的. 在括弧內的"xyz" 會使用JVM 之前創建的對象.

⑨ 字元串匹配演算法是怎麼算的

這是一個畢業老師出的字元串的演算法的題目!這是答案 可以參考一下! boyermoore演算法的sample程序 TCHAR * BoyerMooreSearch(TCHAR *sSrc, TCHAR *sFind) { // // 聲明: // 該段代碼只是BoyerMoore(名字也許不準確) 的基本思想,當 // 然不是最優的,具體完善工作就留給你自己樂!嘻嘻。 // 該演算法的本質就是從字元串的右端而不是左端開始比較,這 // 樣,當查詢不匹配時才有可能直接躍過多個字元(最多可以躍過 // strlen(sFind)個字元), 如果最右邊的字元匹配則回溯。比如: // // pain // ^ 這是第一次比較n和空格比 // The rain in SpainThe rain in Spain // // pain // ^ 這是第二次比較,好爽呀! // The rain in SpainThe rain in Spain // // 當然,這樣比較會產生一些問題,比如: // // pain // ^ (圖1) // The rain in SpainThe rain in Spain // // 如果比較到這兒,大家都會看到,只需再向後移到兩個字元 // 就匹配成功了,但如果接下去還按上面的方法跳strlen( sFind)的 // 話,就會錯過一次匹配!!!!! // // pain // ^ // The rain in SpainThe rain in Spain // // 怎麼辦?當然可以解決!大家回頭看圖1,當時a是pain的子 // 串,說明有可能在不移動strlen(sFind) 的跨度就匹配成功,那就 // 人為地給它匹配成功的機會嘛!串一下pain串, 直接讓兩個a對齊 // 再做比較!呵呵,如果要比較的字元不是pain的子串,當然就可 // 以直接跨過strlen(sFind)個字元了! 不知我說明白沒? // // // 查詢串的長度 int nLenOfFind = lstrlen(sFind); // 被查詢串的長度 int nLenOfSrc = lstrlen(sSrc); // 指向查詢串最後一個字元的指針 TCHAR * pEndOfFind = sFind + nLenOfFind -1; // 指向被查詢串最後一個字元的指針 TCHAR * pEndOfSrc = sSrc + nLenOfSrc -1; // 在比較過程中要用到的兩個指針 TCHAR * pSrc = sSrc; TCHAR * pFind; // 總不能一直讓它比較到 win.com 文件的地址去吧?嘻嘻! while ( pSrc <= pEndOfSrc ) { // 每次匹配都是從右向左,這是本演算法的核心。 pFind = pEndOfFind; // 如果比較不成功,被查詢串指針將向右串的字元數 int nMoveRightSrc; // 比較被查詢串的當前字元是否和查詢串的最右邊字 // 符匹配,如果匹配則回溯比較,如果全匹配了,該 // 干什麼,我就不用說了吧?:-) while ( pFind >= sFind ) { // TNND,白廢功夫比了!看看需要向右移動幾個 // 字元吧(如果說從右到左是本演算法的核心,則 // 判斷向右移幾個字元則是本演算法的技巧)。 if ( *pSrc != *pFind ) { // 被查詢串的當前字元是否在查詢串里? TCHAR * p = strrchr( sFind, *pSrc ); // 沒在,直接移lstrlen(sFind)個字元 if ( NULL == p ) nMoveRightSrc = nLenOfFind; else // 哇塞!真的在,那就只需... nMoveRightSrc = pEndOfFind - p; break; } // 哈!又匹配成功了一個!接著向左回溯... pFind --; pSrc --; } // 如果在上面的while循環里每一次比較都匹配了 // 那就對了唄!告訴用戶找到了 if ( pFind < sFind ) return ( pSrc + 1 ); // 沒匹配成功,nMoveRightSrc上面已經算好了 // 直接用就可以了。 pSrc += nMoveRightSrc; } // 程序運行到這兒肯定是沒指望了! return NULL; } 行了,函數寫完了,我們可以試一下了! void CTNNDDlg::OnButton1() { TCHAR sSrc[] = "The rain in Spain"; TCHAR sFind[]= "pain"; TCHAR * pFound = BoyerMooreSearch( sSrc, sFind ); if ( pFound ) MessageBox(pFound); else MessageBox("沒找到"); } //另外一個 void preBmBc(char *x, int m, int bmBc[]) { int i; for (i = 0; i < ASIZE; ++i) bmBc[i] = m; for (i = 0; i < m - 1; ++i) bmBc[x[i]] = m - i - 1; } void suffixes(char *x, int m, int *suff) { int f, g, i; suff[m - 1] = m; g = m - 1; for (i = m - 2; i >= 0; --i) { if (i > g && suff[i + m - 1 - f] < i - g) suff[i] = suff[i + m - 1 - f]; else { if (i < g) g = i; f = i; while (g >= 0 && x[g] == x[g + m - 1 - f]) --g; suff[i] = f - g; } } } void preBmGs(char *x, int m, int bmGs[]) { int i, j, suff[XSIZE]; suffixes(x, m, suff); for (i = 0; i < m; ++i) bmGs[i] = m; j = 0; for (i = m - 1; i >= -1; --i) if (i == -1 || suff[i] == i + 1) for (; j < m - 1 - i; ++j) if (bmGs[j] == m) bmGs[j] = m - 1 - i; for (i = 0; i <= m - 2; ++i) bmGs[m - 1 - suff[i]] = m - 1 - i; } void BM(char *x, int m, char *y, int n) { int i, j, bmGs[XSIZE], bmBc[ASIZE]; /* Preprocessing */ preBmGs(x, m, bmGs); preBmBc(x, m, bmBc); /* Searching */ j = 0; while (j <= n - m) { for (i = m - 1; i >= 0 && x[i] == y[i + j]; --i); if (i < 0) { OUTPUT(j); j += bmGs[0]; } else j += MAX(bmGs[i], bmBc[y[i + j]] - m + 1 + i); } }

⑩ 面試演算法知識梳理(14) - 數字演算法

面試演算法知識梳理(1) - 排序演算法
面試演算法知識梳理(2) - 字元串演算法第一部分
面試演算法知識梳理(3) - 字元串演算法第二部分
面試演算法知識梳理(4) - 數組第一部分
面試演算法知識梳理(5) - 數組第二部分
面試演算法知識梳理(6) - 數組第三部分
面試演算法知識梳理(7) - 數組第四部分
面試演算法知識梳理(8) - 二分查找演算法及其變型
面試演算法知識梳理(9) - 鏈表演算法第一部分
面試演算法知識梳理(10) - 二叉查找樹
面試演算法知識梳理(11) - 二叉樹演算法第一部分
面試演算法知識梳理(12) - 二叉樹演算法第二部分
面試演算法知識梳理(13) - 二叉樹演算法第三部分

斐波那契數列 滿足下面的通項公式,要求給出 N ,輸出第 N 項的 F(N)

這里介紹兩種解決辦法, 循環演算法 矩陣演算法 。循環演算法比較容易理解,就是從 F(0) 開始,根據通項公式,得到下一個斐波那契數列中的數字即可。

對於上面的通項公式,可以用下面的矩陣乘法的形式來表示

一個台階總共有 n 級,如果一次可以跳 1 級,也可以跳 2 級,求總共有多少總跳法。

由於有兩種跳台階方式,因此跳 n 級台階可以轉換為下面兩個問題之和:

這就和之前的斐波那契數列的通項公式相同。

這個問題,需要先總結一下規律,我們根據數字 N 的 位數 來進行分析:

那麼 N>=1 時才會出現 1 ,並且出現 1 的次數為 1 次

在這種情況下,出現 1 的次數等於個位上出現 1 的次數加上十位上出現 1 的個數。

例如,如果要計算百位上 1 出現的次數,它要受到三方面的影響:百位上的數字,百位以下的數字,百位以上的數字。

對於一個二進制數,例如 1010 ,將其減 1 後得到的結果是 1001 ,也就是將最後一個 1 (倒數第二位)及其之後的 0 變成 1 , 1 變成 0 ,再將該結果與原二進制數相與,也就是 1010 & 1001 = 1000 ,那麼就可以去掉最後一個 1 。

因此,如果需要計算兩個數的二進製表示中有多少位是不同的,可以 先將這兩個數異或 ,那麼不相同的位數就會變成 1 ,之後利用上面的技巧,通過每次去掉最後一個 1 ,來 統計該結果中 1 的個數 ,就可以知道兩個數的二進製表示中有多少是不同的了。

N! 的含義為 1*2*3*...*(N-1)*N ,計算 N! 的十進製表示中,末尾有多少個 0 。

N! 中能產生末尾是 0 的質數組合是 2*5 ,所以 N! 末尾的 0 的個數取決了 2 的個數和 5 的個數的最小值,有因為被 2 整除的數出現的概率大於 5 ,因此 5 出現的次數就是 N! 末尾 0 的個數。因此,該問題就轉換成為計算從 1~N ,每個數可以貢獻 5 的個數,也就是每個數除以 5 的值。

上面的解法需要從 1 到 N 遍歷每一個數,當然還有更加簡便的方法。以 26! 為例,貢獻 5 的數有 5、10、15、20、25 ,一共貢獻了 6 個 5 ,可以理解為 5 的倍數 5、10、15、20、25 貢獻了一個 5 ,而 25 的倍數又貢獻了一個 5 ,得到下面的公式:

首先,讓我們換一個角度考慮,其實這個問題就是求解二進製表示中從最低位開始 0 的個數,因為二進制最低位為 0 代表的是偶數,能夠被 2 整除,所以質因數 2 的個數就是二進製表示中最低位 1 後面的 0 的個數。

因此,我們的實現這就和上面 2.7 中求解質因數 5 的個數是一樣的。

最大公約數 的定義為 兩個或多個整數的共有約數中最大的一個 。這里採用的是 更相止損法 ,其操作步驟為:

則第一步中約掉的若干個 2 與第二步中等數的乘積就是所求的最大公約數。

有限小數或者無限循環小數都可以轉化為分數,例如:

在 http://blog.csdn.net/flyfish1986/article/details/47783545 這邊文章中,詳細地描述了該題的解決思路,核心思想就是將原小數分為 有限部分 無限循環小數 部分,對於這兩部分別進行處理。

閱讀全文

與程序員面試字元串演算法相關的資料

熱點內容
微盟程序員老婆 瀏覽:928
intellij創建java 瀏覽:110
java連接odbc 瀏覽:38
啟動修復無法修復電腦命令提示符 瀏覽:359
手機編程是什麼 瀏覽:97
山東移動程序員 瀏覽:163
蘇州java程序員培訓學校 瀏覽:475
單片機液晶驅動 瀏覽:854
魔拆app里能拆到什麼 瀏覽:130
新預演算法的立法理念 瀏覽:144
wdcpphp的路徑 瀏覽:134
單片機p0口電阻 瀏覽:926
瀏覽器中調簡訊文件夾 瀏覽:594
五菱宏光空調壓縮機 瀏覽:68
為什麼app佔用幾百兆 瀏覽:680
自動解壓失敗叫我聯系客服 瀏覽:484
易語言新手源碼 瀏覽:456
oa伺服器必須有固定ip地址 瀏覽:45
傳奇源碼分析是什麼 瀏覽:269
解放壓縮機支架 瀏覽:255