1. 程式人生 > >面試複習==華山論劍(一)?二分查詢也是病:BSearch

面試複習==華山論劍(一)?二分查詢也是病:BSearch

看到一篇很有意思的文章就動手解決了一下問題。。。覺得有點意思~正逢畢業VS求職VS面試VS....高峰期,各種潮湧。

《程式設計珠璣》中的兩句話: 

  1. 儘管給了那麼充裕的時間,只有大約10%的專業程式設計師能夠寫出正確的二分查詢。
  2. 儘管第一個二分查詢程式於1946年就公佈了,但是第一個沒有bug的二分查詢程式在1962年才出現。

當時看到這的時候,我覺得有點誇張。這裡不去討論是否真的花了20年才人們才寫出正確的程式碼,但這兩句話至少告訴我們,不要小看二分搜尋。

確實,寫過bsearch的人都知道,迭代的出口很難在短時間內想清楚(反正我經常糊塗)。當然,常規的二分搜尋大家現在基本都能寫了,(寫過這麼多次,背也背下來了),但能寫出來不代表真正理解了二分搜尋。比如我們可以改動一下原型:從一個有序陣列中找到大於x且最接近x的數。

說白了就是二分搜尋,但是迭代的出口是什麼的問題?

一、二分查詢演算法的原型JAVA程式碼表示

//傳統二分搜尋   PS:a陣列中的值從小到大排列,找到目標X則返回下標值,未找到則返回-1 
	public static int bsearch(int[] a, int x) {
		int l=0,h=a.length -1 ;
		int m;
		while(h>=l) {
			m=(l+h)/2;
			if(a[m] ==x) {
				return m;
			} else if(a[m] <x){
				l=m+1 ;
			} else {
				h=m-1 ;
			}
		}
		System.out.println("l:"+l+" h:"+h);
		return -1 ;
	}

考慮一下要查詢的元素不在序列中的情況:函式會返回-1,那l和h分別指向什麼呢?

可以證明:l指向大於x的第一個元素,r指向小於x的第一個元素。(為什麼?迭代的最後一步必然是l和h指向同一元素,然後為什麼會變得比h大呢?想想就明白了)


二、變形1

//功能簡介:  在有序陣列中查詢比x大但是最接近x的數
//二分搜尋   PS:a陣列中的值從小到大排列,找到目標X則返回下標值,未找到則返回-1 
	public static int bsearch_more(int[] a, int x) {
		int l=0,h=a.length -1 ;
		int m;
		while(h>=l) {
			m=(l+h)/2;
			if(a[m] ==x) {
				return (m+1)>a.length-1?-1:m+1;
			} else if(a[m] <x){
				l=m+1 ;
			} else {
				h=m-1 ;
			}
		}
		System.out.println("l:"+l+" h:"+h);
		return l ;
	}


三、變形2

//功能簡介:  在有序陣列中查詢比x小但是最接近x的數
//二分搜尋   PS:a陣列中的值從小到大排列,找到目標X則返回下標值,未找到則返回-1 
		public static int bsearch_less(int[] a, int x) {
			int l=0,h=a.length -1 ;
			int m;
			while(h>=l) {
				m=(l+h)/2;
				if(a[m] ==x) {
					return (m-1)<0?-1:m-1;
				} else if(a[m] <x){
					l=m+1 ;
				} else {
					h=m-1 ;
				}
			}
			System.out.println("l:"+l+" h:"+h);
			return h ;
		}


附:主函式測試程式碼JAVA表示

public static void main(String[] args) {
		// TODO Auto-generated method stub
		//傳統二分搜尋
		int[] a = {1,4,7,9,10,17,20} ;
		int sign = bsearch(a,11) ;
		System.out.println(sign);
		sign = bsearch_more(a, 18) ;
		System.out.println(a[sign]);
		sign = bsearch_less(a, 5) ;
		System.out.println(a[sign]);
	}

相關推薦

面試複習==華山論劍二分查詢BSearch

看到一篇很有意思的文章就動手解決了一下問題。。。覺得有點意思~正逢畢業VS求職VS面試VS....高峰期,各種潮湧。 《程式設計珠璣》中的兩句話:  儘管給了那麼充裕的時間,只有大約10%的專業程式設計師能夠寫出正確的二分查詢。 儘管第一個二分查詢程式於1946年就公

演算法--查詢演算法順序查詢二分查詢遞迴和非遞迴方式

我們拋開二分查詢演算法,如果有這樣的一個需求,需要在一些數字中找出有沒有某個數字,我們應該怎麼做?          1 首先我們會想到用什麼資料結構存放這些數? 資料結構就是計算機儲存組織、

Linux系統運維常見面試簡答題15題

數據庫 route add 書寫 iptable sync 語句 日誌 mas ech 1、請描述下linux 系統的開機啟動過程開機加電BIOS自檢———–>MBR引導———–>grub引導菜單———–>加載內核———–>啟動init進程———–&

Java 面試基礎總結

tor rac 時有 線程安全 lec getclass ron 接口 add 1、九種基本數據類型的大小以及它們的封裝類 java提供的九種基本數據類型:boolean、byte(1)、char(2)、short(2)、int(4)、long(8)、float(4)、do

SQL總結基本查詢

平均值 詳細介紹 可用 pac inpu 學習 lsp 多少 但是 SQL查詢的事情很簡單,但是常常因為很簡單的事情而出錯。遇到一些比較復雜的查詢我們更是忘記了SQL查詢的基本語法。 本文希望通過簡單的總結,把常用的查詢方法予以總結,希望能夠明確在心。 場景:學生信息系統

C語言基礎複習筆記指標

最近linux很火,年前對linux再詳細瞭解了個大概,結合在windows平臺活躍與強大無比的C++,最終得出一個結論:C語言依然強大。 過年回來,便對的C語言充滿了興趣,於是乎去網上下載了教程回來,細細研讀,基礎程式設計思想始終是很重要的。 首先,入手的便是C語言的核心精華部分,指標。要

關於Java基礎的複習總結入門篇

千里之堤,毀於雙十一。 主題內容源於當初學Java的幾個筆記本。週末整理換季衣物的時候找到的。重新整理一遍,上傳儲存下來,也是對基礎的複習總結。同時紀念當年初學Java的日子。 1、java發展史 1995誕生於sun公司,被oracle公司收購 開源,免費的 1996年,推出jdk1

[演算法天天見]二分查詢

二分查詢 一、概述 二、演算法 1. 查詢第一個值等於給定值的元素 2. 查詢最後一個值等於給定值的元素 3. 查詢第一個大於等於給定值的元素 4. 查詢最後一個小於等於給定值的元素 一、概述

面試經典考題SQL部分

面試經典考題(一):SQL部分 (1)寫出一條Sql語句: 取出表A中第31到第40記錄(SQLServer, 以自動增長的ID作為主鍵, 注意:ID可能不是連續的。)     --定義臨時表@A併為@A產生資料 declare @A table(id int i

jvm 複習概要 java 記憶體結構

一、記憶體結構 從大結構來說,JAVA虛擬機器記憶體主要分為 執行緒共享區和 執行緒獨佔區,如下圖 1.執行緒共享區 執行緒共享區主要包括java堆和方法區 1.1 java堆 主要存放物件,分為edan區,新生代,老年代,是垃圾收集器的主要管理區域 1.2 方法區

JavaScript複習筆記變數、資料型別和運算子

1、JavaScript用來做什麼 HTML:專門編寫網頁內容的語言 CSS:專門美化網頁內容樣式的語言 JavaScript:專門編寫互動程式的語言 JavaScript包含三個方面:ECMAScript標準+DOM標準+BOM 2、常用語句 在控制檯中輸出一段話 &nbs

hdu1303Doubles二分查詢

Problem Description As part of an arithmetic competency program, your students will be given randomly generated lists of from 2 to 15 unique positive

20181209——複習ElementUI起步

Layout佈局 el-row標籤相當於html的div標籤,給所需要的登入頁面提供了一個div,在div中新增小標籤就行編寫登入頁面程式碼 可以定義佈局flex,在根據flex的屬性justify進行對row調節 type="flex" justify="center||start

資料結構複習筆記——靜態順序表C語言

定義結構體 typedef struct{ int data[MAXSIZE]; //MAXSIZE為最大容量 int length; //當前長度 } Array; 建立順序表 /* 需要接受一個已知的陣列,以及該陣列的長度 按順序將陣列內的值,賦給順

C++面試常溫問題

重點部落格記得看 常用的技術基礎主要包括:程式語言相關;資料結構,作業系統,計算機網路,計算機組成原理;資料庫相關;linux命令列相關;以及常用的工具等等。 程式語言常用有關於C++,python,golang,JAVA等,主要會根據幾種語言的特性來問。

資料庫習題自學練習簡單查詢練習

《資料庫系統概論》(第五版)高等教育出版社 王珊 薩師煊 編著 課後習題自學練習,若有不足望指正。 P70T6 設有一個數據庫SPJ資料庫,包括S、P、J及SPJ 4個關係模式: S(SNO,SNAME,STATUS,CITY); P(PNO,PNAME,COLOR,

python複習筆記

當你用一種語言開始作真正的軟體開發時,你除了編寫程式碼外,還需要很多基本的已經寫好的現成的東西,來幫助你加快開發進度。高階程式語言通常都會提供一個比較完善的基礎程式碼庫,讓你能直接呼叫。Python就為我們提供了非常完善的基礎程式碼庫,覆蓋了網路、檔案、GUI、資料庫、文字等大量內容,被形象地稱作“內建電池

JavaScript複習筆記

1、JavaScript用來做什麼 HTML:專門編寫網頁內容的語言 CSS:專門美化網頁內容樣式的語言 JavaScript:專門編寫互動程式的語言 JavaScript包含三個方面:ECMAScript標準+DOM標準+BOM 2、常用語句 在控制檯中輸出一段

JAVA面試700問

原文地址 譯者:葉文海([email protected]) 1、Java環境中的位元組碼是什麼? 由Java 編譯器生成的一種程式碼。 由JVM生成的一種程式碼。 Java原始檔(Java Source File)的別名。 一種寫在類的例項方法中的程式碼。 答案:由Java 編

java面試12題

java面試12題(一) 文章目錄 java面試12題(一) 1. 為什麼java被稱作“平臺無關的程式語言”? 2. 什麼是java虛擬機器(JVM)? 3.JDK和JRE的區別 4. static關鍵字