劍指offer(java程式碼版)
1,singleTon例項 題目描述:設計一個類,我們只能生成該類的一個例項 //volatile:防止指令重排序 public class singletonClass{
private static volitile singletonClass instance;
private singletonClass(){
}
public static singletonClass getInstance(){
if(instance==null){ synchronized(singletonClass.class){ if(instance==null){ instance = new singletonClass(); } } return instance;
} } }
2,二位陣列中的查詢 在一個二位陣列中,每一行都按照從左到右遞增的順序排列,每一列都按照從上到下的順序排序,完成一個函式,輸入這樣的一個二維陣列和一個整數,判斷陣列中是否包含該整數
public class find(){
public static boolean find(int arr[][],int keyNumber){
int column =arr[0].length-1; int row = 0; while(column>0&&row<arr.length){ if(arr[row][column]==keyNumber){ return true; } else if(arr[arr][column]>keyNumber){ column--; } else{ row++; } }
} return false; } //測試find函式 public static void main(String args[]){ //測試這個陣列 /* * 1 2 8 9 * 2 4 9 12 * 4 7 10 13 * 6 8 11 15 */ int array[][] = new int[4][4]; array[0][0]=1; array[0][1]=2; array[0][2]=8; array[0][3]=9; array[1][0]=2; array[1][1]=4; array[1][2]=9; array[1][3]=12; array[2][0]=4; array[2][1]=7; array[2][2]=10; array[2][3]=13; array[3][0]=6; array[3][1]=8; array[3][2]=11; array[3][3]=15; System.out.println(find(array,7)); System.out.println(find(array,5)); }
3,空格替換 題目描述: 請實現一個函式,將字串的每個空格替換為"%20"。 例如輸入"We are happy",則輸出"We%20are%20happy."。
public class replaceBlank{
public String replace(String input){
StringBuilder build = new StringBuilder();
if(input==null||input.length()==0){
return null;
}
for(int i=0;i<input.length();i++){
if(input.charAt(i)==' '){
builder.append("%");
builder.append("2");
builder.append("0");
}else{
builder.append(input.charAt(i));
}
}
return builder.toString();
} }
//測試用例 public static void main(String[] args){ ReplaceBlank test = new ReplaceBlank();
String str1=“We are happy” System.out.println(test.replace(str1));
}
4,從尾到頭列印連結串列 題目描述:輸入一個連結串列的頭結點,從頭到尾反過來列印每個結點的值
//首先定義連結串列結構 class LinkNode{ LinkNode next; int node_value; }
public class PrintListReverse{ public void reverse(LinkNode headNode){ //用棧的思想來實現連結串列的倒敘輸出 Stack stack = new Stack(); while(headNode!=null){ stack.push(headNode); headNode = headNode.next; } while(!stack.isEmpty()){ System.out.println(stack.pop().node_value+""); } System.out.print(); }
public static void main(String[] args){
PrintListReverse plr = new PrintReverse(); LinkNode node1 = new LinkNode(); LinkNode node2 = new LinkNode(); LinkNode node3 = new LinkNode();
node1.next_value=1; node2.next_value=2; node3.next_value=3;
node1.next=node2; node2.next=node3; plr.reverse(node1); }
}
4,題目描述:輸入某二叉樹的前序遍歷和中序遍歷結果,請重建出該二叉樹。假設輸入的前序遍歷和中序遍歷的結果中都不包含重複的數字。例如輸入前序遍歷序列:{1,2,4,7,3,5,6,8}和中序遍歷{4,7,2,1,5,3,8,6},則重建出圖中所示二叉樹並且輸出它的頭結點。
重建的二叉樹:
//定義二叉樹節點 class BinaryTreeNode{ public int value; public BinaryTreeNode leftNode; public BinaryTreeNode rightNode;
//無參建構函式 public BinaryTreeNode{
}
//定義有參的建構函式 public BinaryTreeNode(int value){ this.value = value; this.leftNode = null; this.rightNode = null; } }
//構造二叉樹 public Class ConstructBinaryTree{
public static BinaryTreeNode construct(int preOrder{},int inOrder{},int length) throws Exception{
if(preOrder ==null||inOrder==null||length<0){
return null;
}
return constructCore(preOrder,0,preOrder.length-1,inOrder,0,inOrder.length - 1);
}
public static BinaryTreeNode constructCore(int preOrder{},
int startPreIndex, int endPreIndex, int inOrder{},
int startInIndex,int endInIndex)throws InvalidPutException{
//頭結點的值
int rootValue = preOrder[startInIndex];
//構建一個只有一個根節點的二叉樹
BinaryTreeNode root = new BinaryTreeNode(rootValue);
//只有一個元素的情況下
if(startPreIndex == endPreIndex){
if(startInIndex == endInIndex
&& preOrder[startInIndex] == inOrder[endInIndex]){
System.out.println("只有一個元素");
return root;
}else{
throw new InvalidPutException();
}
}
//最重要的一步:在中序遍歷中找到根結點的索引
int rootInIndex = startInIndex;
while(rootInIndex<=endInIndex && inOrder[rootInIndex]!=rootValue){
rootInIndex++;
}
if(rootInIndex == endInIndex && inOrder[rootInIndex]!=rootValue){
throw new InvalidPutException();
}
//根結點的左子數的長度
int leftLength = rootInIndex - startInIndex;
//根節點的左子數的最右端的索引值
int leftPreEndIndex = startPreIndex + leftLength;
//構建左子樹
if(leftLength>0){
root.leftNode = constructCore(preOrder,startPreIndex + 1,
leftPreEndIndex, inOrder,startInIndex,rootInIndex - 1);
}
//說明根結點存在右子數
if(leftLength < endPreIndex - startPreIndex){
root.rightNode = constructCore(preOrder,leftPreEndIndex+1,
endPreIndex,inOrder,rootInIndex+1,endInIndex);
}
return root;
}
//按照前序遍歷列印二叉樹的節點 public static void printPreBinaryTree(BinaryTreeNode root){ if(root ==null){ return; }else{ System.out.println(root.value+""); }
if(root.leftNode!=null){
printPreBinaryTree(root.rightNode);
}
if(root.rightNode!=null){
printPreBinaryTree(root.rightNode);
}
}
public static class InvalidPutException extends Exception {
private static final long serialVersionUID = 1L;
}
public static void main(String[] args) throws Exception{ int preOrder[] = {1,2,4,7,3,5,6,8}; int inOrder[] = {4,7,2,1,5,3,8,6}; ConstructBinaryTree test = new ConstructBinaryTree(); printPreBinaryTree(test.construct(preOrder,inOrder,preOrder.length)); }
}
6,用兩個棧實現佇列 題目描述:用兩個棧實現一個佇列。佇列的宣告如下,請實現它的兩個函式appendTail和deleteHead,分別完成在佇列尾部插入結點和在佇列頭部刪除結點的功能。
public class constractQueue{
Stack stack1 = new Stack(); Stack stack2 = new Stack();
public void appendTail(int a){ stack1.push(a); }
public void deleteHead() Throws Exception{ if(stack2.isEmpty){ if(!stack1.isEmpty){ stack2.push(stack1.pop()); } } if(stack2.isEmpty){ System.out.println(“佇列為空不能刪除”); } return stack2.pop(); }
public static void main(String args[]){
ConstractQueue test = new ConstractQueue(); //向空的佇列中新增元素,刪除元素 test.append(“1”); System.out.println(test.deleteHead()); } }
7,旋轉陣列的最小數字 題目描述:把一個數組最開始的若干個元素搬到陣列的末尾,我們稱之為陣列的旋轉。輸入一個遞增排序的陣列的一個旋轉,輸出旋轉陣列的最小元素。例如陣列{3,4,5,1,2}為{1,2,3,4,5}的一個旋轉,該陣列的最小值為1; public class MinInReversingList{
public static int minElement(int array[]) throws Exception{
//條判斷
if(array==null||array.length<=0){
throw new Exception(Invalid parameters);
}
int left = 0;
int right = array.length-1;
int mid = left;
while(array[left]>=array[right]){
//跳出迴圈的條件
if(right-left==1){
mid = right;
break;
}
mid = (left + right)/2;
if(array[left]==array[mid] && array[mid] == array[right]){
return minFromSortSearch(array);
}else{
//演算法的核心思想
if(array[mid]>array[left]){
left = mid;
}
if(array[mid]<=array[right]){
right = mid
}
}
}
return array[right];
} } 8,斐波那契數列 題目描述:寫一個函式,輸入n,求斐波那契數列的第n項,斐波那契數列的定義如下: n=0,f(n)=0 ;n=1,f(n)=1 n>1;f(n)=f(n-1)+f(n-2). 青蛙跳臺階的問題,也可以用裴波那契數列 package Fibonacci;
public class Fibonacci {
public static long Fib2(int n) {
long FibOne = 0;
long FibTwo = 1;
long FibN = 0;
int result[] = { 0,1 };
if (n < 2) {
return result[n];
} else {
for (int i = 2; i <= n; i++) {
FibN = FibTwo + FibOne;
FibOne = FibTwo;
FibTwo = FibN;
}
}
return FibN;
}
public static void main(String[] args) {
// 用解法1求序列的第100項,直接不動了
// System.out.println(Fib1(100));
System.out.println(Fib2(2));
}
} 9,問題描述: 請實現一個函式,輸入一個整數,輸出該數二進位制表示中1的個數。例如把9表示成二進位制是1001,有2位是1 因此如果輸入9,該函式輸出2; public class NumbleOf1{
public int numble(int n ){ int count = 0; int flag = 1; while(flag!=0){ if((n&flag)!=0){ count++; } flag= flag<<1; } return count; }
public static void main(String args){ NumbleOf1 test = new NumbleOf1(); System.out.println(test.numble(9)); }
}
10,問題描述:實現函式double power(double base,int exponent),求base的exponent次方。不能使用庫函式,同時不需要考慮大數問題。
public class Power{
public double power(double base,int export){ double result = 0.0; if(equal(base,0)&& export0){ System.out.println(“0的負數次冪沒有意義”); } if(export0){ return result = 1.0; } if(export<0){ return unsignPower(base,-export); }else{ return unsignPower(base,export); } return result; }
public double unsignPower(double base,int export){ double result = 1.0; for(int i=0;i<export;i++){ result = result * base; } return result; }
//由於計算機有限的保留位數,因此當一個數與0相差0.000001時,預設為0, public boolean equal(double numble1,double numble2){ if((numble1 - numble2>-0.000001)&&(numble1 - numble2<0.000001)){ return ture; } return false; } }