在編程之美3.11一節中,我們遇到這麼一個問題:找出一個有序(字典序)字串數組中等於指定字串的序號,如果有多個元素存在,則返回其中序號最大的。
對於這個問題,我們首先從非降序整形數組來看看如何?,二分尋找的思想很簡單,就是不斷判斷數組中中間位置的元素與關鍵元素的大小關係,從而確定是在數組的左半部分繼續尋找還是在數組的右半部分繼續尋找。下面是Java實現二分尋找的代碼:
package com.part3;//編程之美3.11 二分尋找public class BinarySearch {public static int location(int[] src,int key){return location(src,0,src.length-1,key);}private static int location(int[] src,int start,int end,int key){int s=start,e=end,m;//記錄尋找的首位置,末位置while(s<e-1){m=s+(e-s)/2;if(src[m]<=key){s=m;}else{e=m;}}if(src[e]==key)return e;else if(src[s]==key)return s;elsereturn -1;}public static void main(String[] args) {// TODO Auto-generated method stubint[] array={0,0,0,0,0,0,0};int key=0;System.out.println(key+" 在數組中的位置為:"+location(array,key));}}
測試結果如下:
0 在數組中的位置為:6
如果我們將測試數組更改為{0,1,1,2,3,3,3,3,4,5,6,7,7,7,9},key=5,則我們得到的測試結果如下:
5 在數組中的位置為:9
從結果上看實現是正確的。
為了使所寫的演算法適用於所有實現Comparable介面的鍵,我們將程式修改如下:
package com.part3;import java.util.Comparator;//編程之美3.11 二分尋找public class BinarySearch<Key extends Comparable<Key>> {public int location(Key[] src,Key key){return location(src,0,src.length-1,key);}private int location(Key[] src,int start,int end,Key key){int s=start,e=end,m;while(s<e-1){m=s+(e-s)/2;if(src[m].compareTo(key)<=0){s=m;}else{e=m;}}if(src[e].equals(key))return e;else if(src[s].equals(key))return s;elsereturn -1;}public static void main(String[] args) {// TODO Auto-generated method stubInteger[] array={0,1,1,2,3,3,3,3,4,5,6,7,7,7,9};int key=5;String[] str={"is","is","majing","my","name","name","what","your",};String keystr="name";BinarySearch<Integer> intbs=new BinarySearch<Integer>();BinarySearch<String> strbs=new BinarySearch<String>();System.out.println(key+" 在數組中的位置為:"+intbs.location(array,key));System.out.println(keystr+" 在數組中的位置為:"+strbs.location(str,keystr));}}
測試結果如下:
5 在數組中的位置為:9
name 在數組中的位置為:5
上面的演算法中,要求返回關鍵字的最大序號,下面我們看一下另外一個問題。
對於一個給定的有序(非降序)數組arr,求任意一個i使得arr[i]=key,不存在則返回-1。
Java實現如下:
private int location(Key[] src,int start,int end,Key key)//返回任意一個等於關鍵字key的序號{int s=start,e=end,m;int flag;while(s<=e){m=s+(e-s)/2;flag=src[m].compareTo(key);if(flag==0)return m;else if(flag>0)e=m-1;elses=m+1;}return -1;}
對於{0,1,1,3,3,3,3,4,4,5,6,7,7,7,9}數組測試結果如下:
3 在數組中的位置為:3
對於{"is","is","majing","my","name","name","what","your"}數組測試結果如下:
name 在數組中的位置為:5
與上面的演算法相對應的,還存在下面一個問題:
對於一個給定的有序(非降序)數組arr,求最小的i使得arr[i]=key,不存在則返回-1。
Java實現如下所示:
private int location(Key[] src,int start,int end,Key key){int s=start,e=end,m;while(s<e){m=s+(e-s)/2;if(src[m].compareTo(key)<0){s=m+1;}else{e=m;}}if(src[e].equals(key))return e;elsereturn -1;}測試代碼:public static void main(String[] args) {// TODO Auto-generated method stubInteger[] array={0,1,1,3,3,3,3,4,4,5,6,7,7,7,9};int key=3;String[] str={"is","is","majing","my","name","name","what","your"};String keystr="name";BinarySearch<Integer> intbs=new BinarySearch<Integer>();BinarySearch<String> strbs=new BinarySearch<String>();System.out.println(key+" 在數組中的位置為:"+intbs.location(array,key));System.out.println(keystr+" 在數組中的位置為:"+strbs.location(str,keystr));}
運行結果如下:
3 在數組中的位置為:3
name 在數組中的位置為:4
如果極端一點,所有的元素都相同,如{0,0,0,0,0,0,0},則將會得到如下的運行結果:
0 在數組中的位置為:0
在編程之美中,還存在另外兩個問題
(1)給定一個有序(非降序)數組,求最大的i使得arr[i]小於key,不存在則返回-1;
(2)給定一個有序(非降序)數組,求最小的i使得arr[i]大於key,不存在則返回-1;
至於這兩個問題,完全可以由上面的演算法得到,比如說求解(1),我們只需要找到最小的i使得arr[i]=key,那麼將i減1就可以得到最大的i使得arr[i]小於key了,你說對吧呵呵...問題(2)也可以類似進行處理。
歡迎轉載,轉載請標明出處,謝謝.......