面試題 2 :實現單例模式
1. 餓漢式單例類
public class SingletonClass {
private static final SingletonClass instance=new SingletonClass();
//私有構造函數
private SingletonClass() {}
public static SingletonClass getInstance() {
return instance;
}
}
2. 懶漢式單例模式
public class SingletonClass {
private static SingletonClass instance=null;
//私有構造函數
private SingletonClass() {}
public synchronized static SingletonClass getInstance() {
if(instance==null) {
instance=new SingletonClass();
}
return instance;
}
}
題 面試題 3 :二維數組中的查找
題目描述:一個二維數組,每一行從左到右遞增,每一列從上到下遞增.輸
入一個二維數組和一個整數,判斷數組中是否含有整數。
public class Find {
public static boolean find(int[][] array,int number) {
if(array==null) {
return false;
}
int column=array[0].length-1;
int row=0;
while (row<array.length && column>=0) {
if(array[row][column]==number) {
return true;
}
if(array[row][column]>number) {
column--;
} else {
row++;
}
}
return false;
}
public static void main(String args[]) {
int[][] testarray=new int[4][4];
testarray[0][0]=1;
testarray[0][1]=2;
testarray[0][2]=8;
testarray[0][3]=9;
testarray[1][0]=2;
testarray[1][1]=4;
testarray[1][2]=9;
testarray[1][3]=12;
testarray[2][0]=4;
testarray[2][1]=7;
testarray[2][2]=10;
testarray[2][3]=13;
testarray[3][0]=6;
testarray[3][1]=8;
testarray[3][2]=11;
testarray[3][3]=15;
System.out.println(find(testarray, 1));
}
}
題 面試題 4 :替換空格
題目:請實現一個函數,把字符串中的每個空格替換成“%20”。
public class ReplaceBlank {
public static void main(String args[]) {
String s="We are happy.";
System.out.println(replaceBlank(s));
}
public String replaceBlank(String input) {
if(input==null)
return null;
StringBuffer outputBuffer=new StringBuffer();
for(int i=0; i<input.length(); i++) {
if(input.charAt(i)==' ') {
outputBuffer.append("%");
outputBuffer.append("2");
outputBuffer.append("0");
} else {
outputBuffer.append(String.valueOf(input.charAt(i)));
}
}
return new String(outputBuffer);
}
}
題 面試題 5 : 從尾到頭打印鏈表
題目:輸入一個鏈表的頭結點,從尾到頭反過來打印出每個結點的值。
方法一:非遞歸的方式
public class PrintListReverse {
public static void main (String args[]) {
ListNode node1=new ListNode();
ListNode node2=new ListNode();
ListNode node3=new ListNode();
node1.data=1;
node2.data=2;
node3.data=3;
node1.next=node2;
node2.next=node3;
printListReversversingly test=new printListReversversingly();
test.printListReverse(node1);
}
public static void printListReverse(ListNode headNode) {
Stack<ListNode> stack=new Stack<ListNode>();
while(headNode!=null) {
stack.push(headNode);
headNode=headNode.next;
}
while(!stack.isEmpty()) {
System.out.println(stack.pop().data);
}
}
}
方法二: :
遞歸方式實現
public class PrintListReverse {
public static void main (String args[]) {
ListNode node1=new ListNode();
ListNode node2=new ListNode();
ListNode node3=new ListNode();
node1.data=1;
node2.data=2;
node3.data=3;
node1.next=node2;
node2.next=node3;
printListReversversingly test=new printListReversversingly();
test.printListReverse(node1);
}
public static void printListReverse(ListNode headNode) {
if(headNode!=null) {
if(headNode.next!=null) {
printListReverse(headNode.next);
}
}
System.out.println(headNode.data);
}
}
題 面試題 6 :重建二叉樹
題目描述:輸入二叉樹的前序遍歷和中序遍歷的結果,重建出該二叉樹。假設前
序遍歷和中序遍歷結果中都不包含重複的數字,例如輸入的前序遍歷序列
{1,2,4,7,3,5,6,8}和中序遍歷序列 {4,7,2,1,5,3,8,6}重建出如圖所示的二叉
樹。
public class BinaryTreeNode {
public static int value;
public BinaryTreeNode leftNode;
public BinaryTreeNode rightNode;
}
import java.util.Arrays;
public class Problem6 {
public static void main(String[] args) throws Exception {
int[] preSort={1,2,4,7,3,5,6,8};
int[] inSort={4,7,2,1,5,3,8,6};
BinaryTreeNode root=constructCore(preSort,inSort);
}
public static BinaryTreeNode constructCore(int[]
preorder,int[] inorder) throws Exception {
if(preorder==null||inorder==null) {
return null;
}
if(preorder.length!=inorder.length) {
throw new Exception("長度不一樣,非法的輸入");
}
BinaryTreeNode root=new BinaryTreeNode();
for(int i=0; i<inorder.length; i++) {
if(inorder[i]==preorder[0]) {
root.value=inorder[i];
System.out.println(root.value);
root.leftNode=constructCore(Arrays.copyOfRange(preorder,1,
i+1), Arrays.copyOfRange(inorder, 0, i));
root.rightNode=constructCore(Arrays.copyOfRange(preorder,i+
1, preorder.length),Arrays.copyOfRange(inorder, i+1,
inorder.length));
}
}
return root;
}
}
題 面試題 7 :用兩個棧實現隊列
題目描述:用兩個棧實現一個隊列,實現對了的兩個函數 appendTail 和
deleteHead,分別完成在隊列尾插入結點和在隊列頭部刪除結點的功能。
public class Problem7<T> {
private Stack<T> stack1=new Stack<T>();
private Stack<T> stack2=new Stack<T>();
public void appendTail(T t) {
stack1.push(t);
}
public T deleteHead() throws Exception {
if(stack2.isEmpty()) {
while(!stack1.isEmpty()) {
stack2.push(stack1.pop());
}
}
if(stack2.isEmpty()) {
throw new Exception("隊列爲空,不能刪除");
}
return stack2.pop();
}
public static void main(String args[]) throws Exception {
Problem7<String> p7=new Problem7<>();
p7.appendTail("1");
p7.appendTail("2");
p7.appendTail("3");
p7.deleteHead();
}
}
題 面試題 8 :旋轉數組的最小數字
題目描述:把一個數組最開始的若干個元素搬到數組的末尾,我們稱之爲數組的
旋轉。輸入一個遞增排序的數組的一個旋轉,輸出旋轉數組的最小元素。例如數
組 {3,4,5,1,2}爲 {1,2,3,4,5}的一個旋轉,該數組的最小值爲 1.
public class Problem8 {
public static void main(String[] args) {
Problem8 p8=new Problem8();
//int[] array={1,1,1,2,0};
// int[] array={3,4,5,1,2};
int[] array= {1,0,1,1,1};
System.out.println(p8.findMinNum(array));
}
public Integer findMinNum(int[] array) {
if(array==null) {
return null;
}
int leftIndex=0;
int rightIndex=array.length-1;
int mid=0;
while(array[leftIndex]>=array[rightIndex]) {
if(rightIndex-leftIndex<=1) {
mid=rightIndex;
break;
}
mid=(leftIndex+rightIndex)/2;
if(array[leftIndex]==array[rightIndex]&&array[leftIndex]==a
rray[mid]) {
if(array[leftIndex+1]!=array[rightIndex-1]) {
mid=array[leftIndex+1]<array[rightIndex-1]?(leftIndex+1):(r
ightIndex-1);
break;
} else {
leftIndex++;
rightIndex--;
}
} else {
if(array[mid]>=array[leftIndex])
leftIndex=mid;
else {
if(array[mid]<=array[rightIndex])
rightIndex=mid;
}
}
}
return array[mid];
}
}
題 面試題 9 :斐波那契數列
題目一:寫一個函數,輸入 n,求斐波那契數列的第 n 項。
public class Fibonacci {
public long fibonacci(int n) {
long result=0;
long preOne=0;
long preTwo=1;
if(n==0) {
return preOne;
}
if(n==1) {
return preTwo;
}
for(int i=2; i<=n; i++) {
result=preOne+preTwo;
preOne=preTwo;
preTwo=result;
}
return result;
}
}
題 面試題 10 :二進制中 1 的個數
題目:請實現一個函數,輸入一個整數,輸出該數二進制表示中 1 的個數。例如
把 9 表示成二進制是 1001;有 2 位是 1,因此如果輸入 9,函數輸出 2.
public class Problem10 {
public static void main(String args[]) {
Problem10 test=new Problem10();
System.out.println(test.numberOf1(3));
}
public int numberOf1(int n) {
int count=0;
while(n!=0) {
count++;
n=(n-1) & n;
}
return count;
}
}
題 面試題 11 :數值的整數次方
題目:實現函數 double Power (double base,int exponent),求 base 的 exponent
次方。不得使用庫函數,同時不需要考慮大數問題。import
java.rmi.server.ExportException;
public class Problem11 {
public static void main(String[] args) throws Exception {
Problem11 p11=new Problem11();
System.out.println(p11.power(2.0, 3));
}
public double power(double base,int exponent) throws Exception {
double result=0.0;
if(equal(base,0.0)&&exponent<0) {
throw new Exception("0的負數次冪沒有意義");
}
if(exponent<0) {
result=1.0/powerWithExpoment(base,-exponent);
} else{
result=powerWithExpoment(base, exponent);
}
return result;
}
private double powerWithExpoment(double base, int exponent) {
if(exponent==0) {
return 1;
}
if(exponent==1) {
return base;
}
double result=1.0;
for(int i=1; i<=exponent; i++) {
result=result*base;
}
return result;
}
private boolean equal(double num1, double num2) {
if((num1-num2>-0.0000001)&&num1-num2<0.0000001) {
return true;
} else {
return false;
}
}
}
題 面試題 12 :打印 1 到最大的 n 位數
題目:輸入數字 n,按順序打印出從 1 到最大的 n 位進制數。比如輸入 3,則打
印出 1、2、3 一直到 999.
public class Problem12 {
public static void main(String[] args) {
Problem12 p12=new Problem12();
p12.printToMaxOfNDigits(2);
}
public void printToMaxOfNDigits(int n) {
int[] array=new int[n];
if(n<=0)
return;
printArray(array,0);
}
private void printArray(int[] array,int n) {
for(int i=0; i<10; i++) {
if(n!=array.length) {
array[n]=i;
printArray(array, n+1);
} else {
boolean isFirstNo0=false;
for(int j=0; j<array.length; j++) {
if(array[j]!=0) {
System.out.print(array[j]);
if(!isFirstNo0)
isFirstNo0=true;
} else {
if(isFirstNo0)
System.out.print(array[j]);
}
}
System.out.println();
return;
}
}
}
}
題 面試題 13 :在 O (1 )時間刪除鏈表結點
題目:給定單向鏈表的頭指針和一個結點指針,定義一個函數在 O(1)時間刪除
該結點。
public class Problem13 {
public static void main(String[] args) {
ListNode head=new ListNode();
ListNode second=new ListNode();
ListNode third=new ListNode();
head.nextNode=second;
second.nextNode=third;
head.data=1;
second.data=2;
third.data=3;
Problem13 p13=new Problem13();
p13.deleteNode(head, second);
System.out.println(head.nextNode.data);
}
public void deleteNode(ListNode head,ListNode deListNode) {
if(deListNode==null||head==null) {
return;
}
if(head==deListNode) { //刪除頭結點
head=null;
} else {
if(deListNode.nextNode==null) { //刪除尾結點
ListNode pointListNode=head;
while(pointListNode.nextNode.nextNode!=null) {
pointListNode=pointListNode.nextNode;
}
pointListNode.nextNode=null;
} else {
deListNode.data=deListNode.nextNode.data;
deListNode.nextNode=deListNode.nextNode.nextNode;
}
}
}
}
class ListNode {
int data;
ListNode nextNode;
}
題 面試題 14 :調整數組順序使奇數位於偶數前面
題目:輸入一個整數數組,實現一個函數來調整該函數數組中數字的順序,使得
所有奇數位於數組的前半部分,所有的數組位於數組的後半部分。
public class Problem14 {
public static void main(String args[]) {
int[] array= {1,2,3,4,5,6,7};
Problem14 test=new Problem14();
test.order(array);
for(int item:array)
System.out.println(item);
}
public void order(int[] array) {
if(array==null||array.length==0)
return ;
int start=0;
int end=array.length-1;
while(start<end) {
while(start<end&&!isEven(array[start])) {
start++;
}
while(start<end&&isEven(array[end])) {
end--;
}
if(start<end) {
int temp=array[start];
array[start]=array[end];
array[end]=temp;
}
}
}
private boolean isEven(int n) {
return n%2==0;
}
}
題 面試題 15 :鏈表中倒數第 k 個結點
題目:輸入一個鏈表,輸出該鏈表中倒數第 k 個結點。爲了符合大多數人的習慣,
本題從 1 開始計數,即鏈表的尾結點是倒數第一個結點。例如一個有 6 個結點的
鏈表,從頭結點依次是 1,2,3,4,5,6。倒數第三個結點就是值爲 4 的結點。
public class Problem15 {
public static void main(String[] args) {
ListNode head=new ListNode();
ListNode second=new ListNode();
ListNode third=new ListNode();
ListNode forth=new ListNode();
head.nextNode=second;
second.nextNode=third;
third.nextNode=forth;
head.data=1;
second.data=2;
third.data=3;
forth.data=4;
Problem15 test=new Problem15();
ListNode resultListNode=test.findKToTail(head, 3);
System.out.println(resultListNode.data);
}
public ListNode findKToTail(ListNode head,int k) {
if(head==null||k==0) {
return null;
}
ListNode resultNode=null;
ListNode headListNode=head;
for(int i=0; i<k; ++i) {
if(headListNode.nextNode!=null) {
headListNode=headListNode.nextNode;
} else {
return null;
}
}
resultNode=head;
while(headListNode!=null) {
resultNode=resultNode.nextNode;
headListNode=headListNode.nextNode;
}
return resultNode;
}
}
public class ListNode {
int data;
ListNode nextNode;
}
題 面試題 16 :反轉鏈表
題目:定義一個函數,輸入一個鏈表的頭結點,反轉該鏈表並輸出反轉後鏈表的
頭結點。
public class Problem16 {
public static void main(String[] args) {
ListNode head=new ListNode();
ListNode second=new ListNode();
ListNode third=new ListNode();
ListNode forth=new ListNode();
head.nextNode=second;
second.nextNode=third;
third.nextNode=forth;
head.data=1;
second.data=2;
third.data=3;
forth.data=4;
Problem16 test=new Problem16();
ListNode resultListNode=test.reverseList(head);
System.out.println(resultListNode.data);
}
public ListNode reverseList(ListNode head) {
if(head==null) {
return null;
}
if(head.nextNode==null) {
return head;
}
ListNode preListNode=null;
ListNode nowListNode=head;
ListNode reversedHead=null;
while(nowListNode.nextNode!=null) {
ListNode nextListNode=nowListNode.nextNode;
if(nextListNode==null)
reversedHead=nextListNode;
nowListNode.nextNode=preListNode;
preListNode=nowListNode;
nowListNode=nextListNode;
}
return nowListNode;
}
}
題 面試題 17 :合併兩個排序的鏈表
題目:輸入兩個遞增排序的鏈表,合併這兩個鏈表並使新鏈表中的結點仍然是按
照遞增排序的。
public class Problem17 {
public static void main(String[] args) {
ListNode head1=new ListNode();
ListNode second1=new ListNode();
ListNode head2=new ListNode();
ListNode second2=new ListNode();
ListNode third2=new ListNode();
head1.nextNode=second1;
head2.nextNode=second2;
second2.nextNode=third2;
head1.data=1;
second1.data=3;
head2.data=2;
second2.data=2;
third2.data=2;
Problem17 test=new Problem17();
ListNode result=test.mergeList(head1, head2);
System.out.println(result.nextNode.nextNode.nextNode.nextNo
de.data);
}
public ListNode mergeList(ListNode head1,ListNode head2) {
if(head1==null) {
return head2;
} else if(head2==null) {
return head1;
}
ListNode mergeHead=null;
if(head1.data<head2.data) {
mergeHead=head1;
mergeHead.nextNode=mergeList(head1.nextNode,head2);
} else {
mergeHead=head2;
mergeHead.nextNode=mergeList(head1, head2.nextNode);
}
return mergeHead;
}
}
題 面試題 18 :樹的子結構
題目:輸入兩顆二叉樹 A 和 B,判斷 B 是不是 A 的子結構。
public class Problem18 {
public static void main(String args[]) {
BinaryTreeNode root1=new BinaryTreeNode();
BinaryTreeNode node1=new BinaryTreeNode();
BinaryTreeNode node2=new BinaryTreeNode();
BinaryTreeNode node3=new BinaryTreeNode();
BinaryTreeNode node4=new BinaryTreeNode();
BinaryTreeNode node5=new BinaryTreeNode();
BinaryTreeNode node6=new BinaryTreeNode();
root1.leftNode=node1;
root1.rightNode=node2;
node1.leftNode=node3;
node1.rightNode=node4;
node4.leftNode=node5;
node4.rightNode=node6;
root1.value=8;
node1.value=8;
node2.value=7;
node3.value=9;
node4.value=2;
node5.value=4;
node6.value=7;
BinaryTreeNode root2=new BinaryTreeNode();
BinaryTreeNode a=new BinaryTreeNode();
BinaryTreeNode b=new BinaryTreeNode();
root2.leftNode=a;
root2.rightNode=b;
root2.value=8;
a.value=9;
b.value=2;
Problem18 test=new Problem18();
System.out.println(test.hasSubTree(root1, root2));
}
public boolean hasSubTree(BinaryTreeNode root1,BinaryTreeNode
root2) {
boolean result=false;
if(root1!=null&&root2!=null) {
if(root1.value==root2.value) {
result=doesTree1HavaTree2(root1,root2);
if(!result)
result=hasSubTree(root1.leftNode, root2);
if(!result)
result=hasSubTree(root1.rightNode, root2);
}
}
return result;
}
private boolean doesTree1HavaTree2(BinaryTreeNode root1,
BinaryTreeNode root2) {
if(root2==null) {
return true;
} else if(root1==null)
return false;
if(root1.value!=root2.value) {
return false;
}
return doesTree1HavaTree2(root1.leftNode, root2.leftNode)&&
doesTree1HavaTree2(root1.rightNode, root2.rightNode);
}
}
題 面試題 19 :二叉樹的鏡像
題目:請完成一個函數,輸入一個二叉樹,該函數輸出它的鏡像。
public class Problem19 {
public static void main(String[] args) {
BinaryTreeNode root1=new BinaryTreeNode();
BinaryTreeNode node1=new BinaryTreeNode();
BinaryTreeNode node2=new BinaryTreeNode();
BinaryTreeNode node3=new BinaryTreeNode();
BinaryTreeNode node4=new BinaryTreeNode();
BinaryTreeNode node5=new BinaryTreeNode();
BinaryTreeNode node6=new BinaryTreeNode();
root1.leftNode=node1;
root1.rightNode=node2;
node1.leftNode=node3;
node1.rightNode=node4;
node4.leftNode=node5;
node4.rightNode=node6;
root1.value=8;
node1.value=8;
node2.value=7;
node3.value=9;
node4.value=2;
node5.value=4;
node6.value=7;
Problem19 test=new Problem19();
BinaryTreeNode
rootBinaryTreeNode=test.mirrorBinaryTree(root1);
System.out.println(root1.rightNode.value);
}
public BinaryTreeNode mirrorBinaryTree(BinaryTreeNode root) {
if(root==null) {
return null;
}
if(root.leftNode==null&&root.rightNode==null)
return null;
Stack<BinaryTreeNode> stack=new Stack<BinaryTreeNode>();
while(root!=null||!stack.isEmpty()) {
while(root!=null) {
BinaryTreeNode temp=root.leftNode;
root.leftNode=root.rightNode;
root.rightNode=temp;
stack.push(root);
root=root.leftNode;
}
root=stack.pop();
root=root.rightNode;
}
return root;
}
}
題 面試題 20 :順時針打印矩陣
題目:輸入一個矩陣,按照從外向裏以順時針的順序依次打印出每一個數字。
public class Problem20 {
public static void main(String[] args) {
int[][] array= {
{1,2,3,4},{5,6,7,8},{9,10,11,12},{13,14,15,16}
};
Problem20 testCircle=new Problem20();
testCircle.printMatixClockwisely(array);
}
public void printMatixClockwisely(int[][] array) {
if(array==null)
return;
int start=0;
while(array[0].length>start*2&&array.length>start*2) {
printOneCircle(array,start);
start++;
}
}
private void printOneCircle(int[][] array, int start) {
for(int i=start; i<array[0].length-start; i++) {
System.out.print(array[start][i]+" ");
}
if(array.length-1-start>start) {
for(int i=start+1; i<array.length-start-1; i++) {
System.out.print(array[i][array[0].length-1-start]+" ");
}
}
if(array[0].length-start-1>start &&
array.length-start-1>start) {
for(int i=array.length-start-1; i>start; i--) {
System.out.print(array[array.length-start-1][i]+" ");
}
}
if(array.length-1-start>start &&
array[0].length-1-start>start) {
for(int i=array.length-start-1; i>start; i--) {
System.out.print(array[i][start]+" ");
}
}
}
}
題 面試題 21 :包含 min 函數的棧
題目:定義棧的數據結構,請在該類型中實現一個能夠得到棧的最小元素的min
函數。在該棧中,調用min、push及pop德爾時間複雜度都是O(1)
public class Problem21 extends MyStack<Integer> {
public static void main(String[] args) {
Problem21 test=new Problem21();
test.push(3);
test.push(2);
test.push(1);
test.push(4);
test.push(5);
System.out.println(test.min());
}
private MyStack<Integer> minStack=new MyStack<Integer>();
private MyStack<Integer> dataStack=new MyStack<Integer>();
public void push(Integer item) {
dataStack.push(item);
if(minStack.length==0||item<=minStack.head.data) {
minStack.push(item);
} else {
minStack.push(minStack.head.data);
}
}
public Integer pop() {
if(dataStack.length==0||minStack.length==0) {
return null;
}
minStack.pop();
return dataStack.pop();
}
public Integer min() {
if(minStack.length==0)
return null;
return minStack.head.data;
}
}
題 面試題 22 :棧的壓入、彈出序列
題目:輸入兩個整數序列,第一個序列表示棧的壓入順序,請判斷第二個序列是
否爲該棧的彈出序列。假設壓入棧的所有數字均不相等。例如壓棧序列爲 1、2、
3、4、5.序列 4、5、3、2、1 是壓棧序列對應的一個彈出序列,但 4、3、5、1、
2 卻不是。
public class Problem22 {
public static void main(String[] args) {
int[] array1= {1,2,3,4,5};
int[] array2= {4,3,5,2,1};
Problem22 test=new Problem22();
System.out.println(test.isPopOrder(array1, array2));
}
public boolean isPopOrder(int[] line1,int[] line2) {
if(line1==null||line2==null) {
return false;
}
int point1=0;
Stack<Integer> stack=new Stack<Integer>();
for(int i=0; i<line2.length; i++) {
if(!stack.isEmpty()&&stack.peek()==line2[i]) {
stack.pop();
} else {
if(point1==line1.length) {
return false;
} else {
do {
stack.push(line1[point1++]);
} while(stack.peek()!=line2[i]&&point1!=line1.length);
if(stack.peek()==line2[i])
stack.pop();
else
return false;
}
}
}
return true;
}
}
題 面試題 23 :從上往下打印二叉樹
題目:從上往下打印二叉樹的每個結點,同一層的結點按照從左到右的順序打印。
import java.util.LinkedList;
import java.util.Queue;
import com.utils.BinaryTreeNode;
public class Problem23 {
public static void main(String args[]) {
BinaryTreeNode root1=new BinaryTreeNode();
BinaryTreeNode node1=new BinaryTreeNode();
BinaryTreeNode node2=new BinaryTreeNode();
BinaryTreeNode node3=new BinaryTreeNode();
BinaryTreeNode node4=new BinaryTreeNode();
BinaryTreeNode node5=new BinaryTreeNode();
BinaryTreeNode node6=new BinaryTreeNode();
root1.leftNode=node1;
root1.rightNode=node2;
node1.leftNode=node3;
node1.rightNode=node4;
node4.leftNode=node5;
node4.rightNode=node6;
root1.value=8;
node1.value=8;
node2.value=7;
node3.value=9;
node4.value=2;
node5.value=4;
node6.value=7;
Problem23 test=new Problem23();
test.printFromTopToBottom(root1);
}
public void printFromTopToBottom(BinaryTreeNode root) {
if(root==null)
return;
Queue<BinaryTreeNode> queue=new
LinkedList<BinaryTreeNode>();
queue.add(root);
while(!queue.isEmpty()) {
BinaryTreeNode node=queue.poll();
System.out.print(node.value);
if(node.leftNode!=null) {
queue.add(node.leftNode);
}
if(node.rightNode!=null) {
queue.add(node.rightNode);
}
}
}
}
題 面試題 24 :二叉搜索樹的後序遍歷序列
題目:輸入一個整數數組,判斷該數組是不是某二叉搜索樹的後序遍歷的結果。
是則返回true,否則返回false。
public class Problem24 {
public static void main(String[] args) {
int[] array= {5,7,6,9,11,10,8};
//int[] array={7,4,6,5};
//int[] array={6,7,8,5};
Problem24 p24=new Problem24();
System.out.println(p24.verfiySequenceOfBST(array));
}
public boolean verfiySequenceOfBST(int[] sequence) {
if(sequence==null||sequence.length==0)
return false;
int length=sequence.length;
int root=sequence[length-1];
int cut=0;
for(int i=0; i<length-1; i++) {
if(sequence[i]>root)
cut=i+1;
break;
}
if(cut==0) {
verfiySequenceOfBST(Arrays.copyOfRange(sequence, 0,
length-1));
} else {
for(int j=cut; j<length-1; j++) {
if(sequence[j]<root)
return false;
}
}
boolean left=true;
if(cut>0)
left= verfiySequenceOfBST(Arrays.copyOfRange(sequence,
0, cut));
boolean right=true;
if(cut<length-1)
right=
verfiySequenceOfBST(Arrays.copyOfRange(sequence,cut,length-1);
return (right&&left);
}
}
題 面試題 25 :二叉樹中和爲某一值的路徑
題目:輸入一顆二叉樹和一個整數,打印出二叉樹中結點值的和爲輸入整數的所
有路徑。從樹的根節點開始往下一直到葉結點所經過的結點形成一條路徑。
public class Problem25 {
public static void main(String args[]) { {
BinaryTreeNode root1=new BinaryTreeNode();
BinaryTreeNode node1=new BinaryTreeNode();
BinaryTreeNode node2=new BinaryTreeNode();
BinaryTreeNode node3=new BinaryTreeNode();
BinaryTreeNode node4=new BinaryTreeNode();
root1.leftNode=node1;
root1.rightNode=node2;
node1.leftNode=node3;
node1.rightNode=node4;
root1.value=10;
node1.value=5;
node2.value=12;
node3.value=4;
node4.value=7;
Problem25 testFindPath=new Problem25();
testFindPath.findPath(root1, 22);
}
}
public void findPath(BinaryTreeNode root,int sum) {
if(root==null)
return;
Stack<Integer> stack=new Stack<Integer>();
int currentSum=0;
findPath(root,sum,stack,currentSum);
}
}
private void findPath(BinaryTreeNode root, int sum, Stack<Integer>
stack,int currentSum) {
currentSum+=root.value;
stack.push(root.value);
if(root.leftNode==null&&root.rightNode==null) {
if(currentSum==sum) {
System.out.println(" 找到一個路徑 ");
for(int path:st ack) {
System.out.print(path+" ");
}
}
System.out.println();
}
}
}
}
if(root.leftNode!=null) {
findPath(root.leftNode, sum, stack, currentSum);
}
}
if(root.rightNode!=null) {
findPath(root.rightNode, sum, stack, currentSum);
}
}
stack. pop();
}
}
}
}
題 面試題 26 :複雜鏈表的複製
題目:實現函數複製一個複雜鏈表。在複雜鏈表中,每個結點除了有一個 next
指針指向下一個結點外,還有一個指向鏈表中任意結點或 null。
package com.example.offer26_40;
public class Problem26 {
public static void main(String[] args) {
Problem26 testClone=new Problem26();
ComplexListNode root=new ComplexListNode();
ComplexListNode node1=new ComplexListNode();
ComplexListNode node2=new ComplexListNode();
ComplexListNode node3=new ComplexListNode();
ComplexListNode node4=new ComplexListNode();
root.data=1;
node1.next=node2;
node2.next=node3;
node3.next=node4;
root.data=1;
node1.data=2;
node2.data=3;
node3.data=4;
node4.data=5;
root.sibling=node1;
node1.sibling=root;
node3.sibling=node1 ;
ComplexListNode result=testClone.clone(root);
System.out.println(result.data);
}
public ComplexListNode clone(ComplexListNode head) {
cloneNodes(head);
connectSiblingNodes(head);
return reconnectNodes(head);
}
public void cloneNodes(ComplexListNode head) {
ComplexListNode node=head;
while(node!=null) {
ComplexListNode cloneNode=new ComplexListNode();
cloneNode.data=node.data;
cloneNode.next=node.next;
cloneNode.sibling=null;
node.next=cloneNode;
node=cloneNode.next;
}
}
public void connectSiblingNodes(ComplexListNode head) {
ComplexListNode node=head;
while(node!=null) {
ComplexListNode clonedNode=node.next;
if(node.sibling!=null) {
clonedNode.sibling=node.sibling.next;
}
node=clonedNode.next;
}
}
public ComplexListNode reconnectNodes(ComplexListNode head) {
ComplexListNode node=head;
ComplexListNode clonedHead=null;
ComplexListNode clonedNode=null;
if(node!=null) {
clonedNode=node.next;
clonedHead=clonedNode;
node.next=clonedNode.next;
node=node.next;
}
while(node!=null) {
clonedNode.next=node.next;
clonedNode=clonedHead.next;
node.next=clonedNode.next;
node=node.next;
}
return clonedHead;
}
}
class ComplexListNode {
int data;
ComplexListNode next;
ComplexListNode sibling;
}
題 面試題 27 :二叉搜索樹與雙向鏈表
題目:輸入一棵二叉搜索樹,將該二叉搜索樹轉換成一個排序的雙向鏈表。要求
不能創建任何新的結點,只能調整樹中結點指針的指向。
public class Problem27 {
public BinaryTreeNode convert(BinaryTreeNode root) {
BinaryTreeNode lastNodeList=null;
convertNode(root,lastNodeList);
while(lastNodeList!=null&&lastNodeList.leftNode!=null) {
lastNodeList=lastNodeList.leftNode;
}
return lastNodeList;
}
private void convertNode(BinaryTreeNode root, BinaryTreeNode
lastNodeList) {
if(root==null)
return;
BinaryTreeNode cuurent=root;
if(cuurent.leftNode!=null) {
convertNode(cuurent.leftNode, lastNodeList);
}
cuurent.leftNode=lastNodeList;
if(lastNodeList!=null)
lastNodeList.rightNode=cuurent;
lastNodeList=cuurent;
if(cuurent.rightNode!=null) {
convertNode(cuurent.rightNode, lastNodeList);
}
}
}
題 面試題 28 :字符串的排列
題目:輸入一個字符串,打印出該字符串中字符的所有排列。
public class Problem28 {
public static void main(String args[]) {
Problem28 testPermutation=new Problem28();
testPermutation.permutation("abcd");
}
public void permutation(String str) {
int count=0;
if(str==null)
return;
char[] chs=str.toCharArray();
int point=0;
System.out.print(chs);
System.out.print(" ");
count++;
char temp1=chs[point];
chs[point]=chs[++point];
chs[point]=temp1;
while(!String.valueOf(chs).equals(str)) {
System.out.print(chs);
System.out.print(" ");
count++;
if(point==chs.length-1) {
char temp=chs[point];
chs[point]=chs[0];
chs[0]=temp;
point=0;
} else {
char temp=chs[point];
chs[point]=chs[++point];
chs[point]=temp;
}
}
System.out.println(count);
}
}
題 面試題 29 :數組中出現次數超過一半的數組
題目:數組中有一個數字出現次數超過數組長度的一半,請找出這個數字。例如
輸入一個長度爲9的數組 {1,2,3,2,2,2,5,4,2}。2出現的次數超過數組長度的
一半,因此輸出2.
public class Problem29 {
public static void main(String[] args) {
int[] array= {1,2,3,2,2,2,5,4,2};
Problem29 p=new Problem29();
System.out.println(p.moreThanHalfNum(array));
}
public Integer moreThanHalfNum(int[] array) {
if(array==null)
return null;
int count=0;
Integer resultInteger=null;
for(int i=0; i<array.length; i++) {
if(count==0) {
resultInteger=array[i];
count=1;
} else if(array[i]==resultInteger)
count++;
else
count--;
}
if(checkMoreThanHalf(array,resultInteger))
return resultInteger;
else
return null;
}
private boolean checkMoreThanHalf(int[] array, Integer number) {
int times=0;
for(int i=0; i<array.length; i++) {
if(array[i]==number)
times++;
}
if(times*2<=array.length)
return false;
else
return true;
}
}
面試題 30:最小的 k 個數。
題目:輸入 n 個整數,找出其中最小的 k 個數。例如輸入 4,5,1,6,2,7,3,8 這
8 個數字,則最少的 4 個數字是 1,2,3,4.
public class Problem30 {
public static void main(String[] args) {
Problem30 test=new Problem30();
int[] array= {4,5,1,6,2,7,3,8};
test.getLeastNumbers(array,2);
}
public void getLeastNumbers(int[] array,int k) {
if(array==null||k<0||k>array.length)
return;
int[] kArray=Arrays.copyOfRange(array, 0, k);
buildMaxHeap(kArray);
for(int i=k; i<array.length; i++) {
if(array[i]<kArray[0]) {
kArray[0]=array[i];
maxHeap(kArray,0);
}
}
for(int i:kArray)
System.out.print(i);
}
private void maxHeap(int[] kArray, int i) {
int left=2*i;
int right=left+1;
int largest=0;
if(right<kArray.length&&kArray[left]>kArray[i])
largest=left;
else
largest=i;
if(right<kArray.length&&kArray[right]>kArray[largest])
largest=right;
if(largest!=i) {
int temp=kArray[i];
kArray[i]=kArray[largest];
kArray[largest]=temp;
maxHeap(kArray, largest);
}
}
private void buildMaxHeap(int[] kArray) {
for(int i=kArray.length/2; i>=0; i--)
maxHeap(kArray, i);
}
}
題 面試題 31 :連續子數組的最大和
題目:輸入一個整型數組,數組裏有正數也有負數。數組中一個或連續的多個整
數組成一個子數組。求所有子數組的和的最大值。要求時間複雜度爲 O(n)。例
如輸入的數組爲 {1,-2,3,10,-4,7,2,-5},和最大的子數組爲 {3,10,-4,7,2}。
public class Problem31 {
public static void main(String[] args) {
Problem31 p=new Problem31();
int[] array= {1,-2,3,10,-4,7,2,-5};
System.out.println(p.findGreatestSubArray(array));
}
public int findGreatestSubArray(int[] array) {
if(array==null)
return 0;
int currentSum=0;
int greatestSum=0;
for(int i=0; i<array.length; i++) {
if(currentSum<=0) {
currentSum=array[i];
} else {
currentSum+=array[i];
}
if(currentSum>greatestSum)
greatestSum=currentSum;
}
return greatestSum;
}
}
題 面試題 32 :從 1 到 到 n 整數中 1 出現的次數
題目:輸入一個整數 n,求從 1 到 n 這 n 個整數的十進制表示中 1 出現的次
數。例如輸入 12,這些整數中包含 1 的數字有 1,10,11,12,1 一共出現了 5 次。
解題思路:解法二告訴我們 1~ N 中"1"的個數跟最高位有關,那我們換個角
度思考,給定一個 N,我們分析 1~N 中的數在每一位上出現 1 的次數的和,看看
每一位上"1"出現的個數的和由什麼決定。
1 位數的情況:在解法二中已經分析過,大於等於 1 的時候,有 1 個,小於 1 就
沒有。
2 位數的情況:N=13,個位數出現的 1 的次數爲 2,分別爲 1 和 11,十位數出現 1
的次數爲 4,分別爲 10,11,12,13,所以 f(N) = 2+4。N=23,個位數出現的 1 的
次數爲3,分別爲1,11,21,十位數出現1的次數爲10,分別爲10~19,f(N)=3+10。
由此我們發現,個位數出現 1 的次數不僅和個位數有關,和十位數也有關,如果
個位數大於等於 1,則個位數出現 1 的次數爲十位數的數字加 1;如果個位數爲
0,個位數出現 1 的次數等於十位數數字。而十位數上出現 1 的次數也不僅和十
位數相關,也和個位數相關:如果十位數字等於 1,則十位數上出現 1 的次數爲
個位數的數字加 1,假如十位數大於 1,則十位數上出現 1 的次數爲 10。
3 位數的情況:
N=123,個位出現 1 的個數爲 13:1,11,21,…,91,101,111,121。十位出現 1 的
個數爲 20:10~19,110~119。百位出現 1 的個數爲 24:100~123。
我們可以繼續分析 4 位數,5 位數,推導出下面一般情況: 假設 N,我們要計算
百位上出現 1 的次數,將由三部分決定:百位上的數字,百位以上的數字,百位
一下的數字。
如果百位上的數字爲 0,則百位上出現 1 的次數僅由更高位決定,比如 12013,
百位出現 1 的情況爲 100~199,1100~1199,2100~2199,…,11100~11199,共 1200
個。等於更高位數字乘以當前位數,即 12 * 100。
如果百位上的數字大於 1,則百位上出現 1 的次數僅由更高位決定,比如 12213,
百位出現 1 的情況爲 100~199,1100~1199,2100~2199,…,11100~11199,
12100~12199 共 1300 個。等於更高位數字加 1 乘以當前位數,即(12 + 1)*100。
如果百位上的數字爲 1,則百位上出現 1 的次數不僅受更高位影響,還受低位影
響。例如 12113,受高位影響出現 1 的情況:100~199,1100~1199,2100~2199,…,
11100~11199,共 1200 個,但它還受低位影響,出現 1 的情況是 12100~12113,
共 114 個,等於低位數字 113+1。
public class Problem32 {
public static void main(String[] args) {
Problem32 p=new Problem32();
System.out.println(p.countOne(123));
}
public long countOne(long n) {
long count = 0;
long i = 1;
long current = 0,after = 0,before = 0;
while((n / i) != 0) {
current = (n / i) % 10; //當前位數字
before = n / (i * 10); //高位數字
after = n - (n / i) * i; //低位數字
if (current > 1)
count = count + (before + 1) * i;
else if (current == 0)
count = count + before * i;
else if(current == 1)
count = count + before * i + after + 1;
i = i * 10;
}
return count;
}
}
題 面試題 33 :把數組排成最小的數
題目:輸入一個正整數數組,把數組裏所有數字拼接起來排成一個數,打印能拼
接出的所有數字的最小的一個。例如輸入 {3,32,321},則打印最小的數字是
321323.
public class Problem33 {
public static void main(String[] args) {
Problem33 test=new Problem33();
int[] array= {3,32,321};
test.printMin(array);
}
public void printMin(int[] array) {
int[] clone=array.clone();
printMinNumber(clone,0,clone.length-1);
for(int i:clone)
System.out.print(i);
}
private void printMinNumber(int[] array, int start, int end) {
if(start<end) {
int main_number=array[end];
int small_cur=start;
for(int j=start; j<end; j++) {
if(isSmall(String.valueOf(array[j]),String.valueOf(main_num
ber))) {
int temp=array[j];
array[j]=array[small_cur];
array[small_cur]=temp;
small_cur++;
}
}
array[end]=array[small_cur];
array[small_cur]=main_number;
printMinNumber(array, 0, small_cur-1);
printMinNumber(array, small_cur+1, end);
}
}
private boolean isSmall(String m, String n) {
String left=m+n;
String right=n+m;
boolean result=false;
for(int i=0; i<left.length(); i++) {
if(left.charAt(i)<right.charAt(i))
return true;
else if(left.charAt(i)>right.charAt(i))
return false;
}
return result;
}
}
題 面試題 34 :醜數
題目:我們把只包含因子 2,3,和 5 的稱爲醜數。求按從小到大的順序的第 1500
個醜數。例如 6、8 都是醜數,但 14 不是,因爲它包含因子 7.習慣上我們把 1
當做第一個醜數。
public class Problem34 {
public static void main(String[] args) {
Problem34 p=new Problem34();
System.out.println(p.getUglyNumber(1500));
}
public int getUglyNumber(int n) {
if(n<0)
return 0;
int[] uglyArray=new int[n];
uglyArray[0]=1;
int multiply2=1;
int multiply3=1;
int multiply5=1;
for(int i=1; i<uglyArray.length; i++) {
int min=min(multiply2*2,multiply3*3,multiply5*5);
uglyArray[i]=min;
while(multiply2*2<=min)
multiply2++;
while(multiply3*3<=min)
multiply3++;
while(multiply5*5<=min)
multiply5++;
}
return uglyArray[n-1];
}
private int min(int i, int j, int k) {
int min=(i<j)?i:j;
return (min<k)?min:k;
}
}
題 面試題 35 :第一個只出現一次的字符
題目:在字符串中找出第一個只出現一次的字符。如果輸入“abaccdeff”,則
輸出‘b’。
public class Problem35 {
public static void main(String[] args) {
Problem35 p=new Problem35();
System.out.println(p.firstNotRepeatChar("agbaccdeff"));
}
public Character firstNotRepeatChar(String str) {
if(str==null)
return null;
char[] strChar=str.toCharArray();
LinkedHashMap<Character, Integer> hash=new
LinkedHashMap<Character, Integer>();
for(char item:strChar) {
if(hash.containsKey(item))
hash.put(item, hash.get(item)+1);
else
hash.put(item, 1);
}
for(char key:hash.keySet()) {
if(hash.get(key)==1)
return key;
}
return null;
}
}
題 面試題 36 :數組中的逆序對
題目:在數組中的兩個數字如果前一個數字大於後一個數字,則這兩個數字組成
一個逆序對。輸入一個數組,求出這個數組的逆序對的總數。例如在數組 {7,5,6,4}
中,一共存在 5 個逆序對,分別是(7,6)、(7、5),(7、4),(6、4),
(5、4)。
public class Problem36 {
public static void main(String[] args) {
Problem36 p=new Problem36();
int[] array= {7,5,6,4};
System.out.println(p.inversePairs(array));
}
public int inversePairs(int[] array) {
if(array==null)
return 0;
int[] copy=array.clone();
return mergeSort(array,copy,0,array.length-1);
}
private int mergeSort(int[] array, int[] result, int start, int
end) {
if(start==end) {
result[start]=array[start];
return 0;
}
int length=(end-start)/2;
int left=mergeSort(result, array, start, start+length);
int right=mergeSort(result, array, start+length+1, end);
int leftIndex=start+length;
int rightIndex=end;
int count=0;
int point=rightIndex;
while(leftIndex>=start&&rightIndex>=start+length+1) {
if(array[leftIndex]>array[rightIndex]) {
result[point--]=array[leftIndex--];
count+=rightIndex-start-length;
} else {
result[point--]=array[rightIndex--];
}
}
for(int i=leftIndex; i>=start; i--)
result[point--]=array[i];
for(int j=rightIndex; j>=start+length+1; j--)
result[point--]=array[j];
return left+right+count;
}
}
題 面試題 37 :兩個鏈表的第一個公共結點
題目:輸入兩個鏈表,找出它們的第一個公共結點。
import com.utils.ListNode;
public class Problem37 {
public static void main(String[] args) {
ListNode head1=new ListNode();
ListNode second1=new ListNode();
ListNode third1=new ListNode();
ListNode forth1=new ListNode();
ListNode fifth1=new ListNode();
ListNode head2=new ListNode();
ListNode second2=new ListNode();
ListNode third2=new ListNode();
ListNode forth2=new ListNode();
head1.nextNode=second1;
second1.nextNode=third1;
third1.nextNode=forth1;
forth1.nextNode=fifth1;
head2.nextNode=second2;
second2.nextNode=forth1;
third2.nextNode=fifth1;
head1.data=1;
second1.data=2;
third1.data=3;
forth1.data=6;
fifth1.data=7;
head2.data=4;
second2.data=5;
third2.data=6;
forth2.data=7;
Problem37 test=new Problem37();
System.out.println(test.findFirstCommonNode(head1,
head2).data);
}
public ListNode findFirstCommonNode(ListNode head1,ListNode
head2) {
int len1=getListLength(head1);
int len2=getListLength(head2);
ListNode longListNode=null;
ListNode shortListNode=null;
int dif=0;
if(len1>len2) {
longListNode=head1;
shortListNode=head2;
dif=len1-len2;
} else {
longListNode=head2;
shortListNode=head1;
dif=len2-len1;
}
for(int i=0; i<dif; i++) {
longListNode=longListNode.nextNode;
}
while(longListNode!=null&&shortListNode!=null
&&longListNode!=shortListNode) {
longListNode=longListNode.nextNode;
shortListNode=shortListNode.nextNode;
}
return longListNode;
}
private int getListLength(ListNode head1) {
int result=0;
if(head1==null)
return result;
ListNode point=head1;
while(point!=null) {
point=point.nextNode;
result++;
}
return result;
}
}
題 面試題 38 :數字在排序數組中出現的次數
題目:統計一個數字在排序數組中出現的次數。例如輸入排序數組 {1,2,3,3,3,
3,3,4,5
}和數字 3,由於 3 在這個數組中出現了 4 次,因此輸出 4。
public class Problem38 {
public static void main(String[] args) {
Problem38 p=new Problem38();
int[] array= {1,2,3,3,3,3,4,5};
System.out.println(p.getNumberOfK(array, 3));
}
private int getNumberOfK(int[] array, int k) {
int number=0;
if(array!=null) {
int first=getFirstK(array,k,0,array.length-1);
int last=getLastK(array,k, 0, array.length-1);
if(first>-1&&last>-1)
number=last-first+1;
}
return number;
}
private int getFirstK(int[] array, int k,int start, int end) {
if(start>end)
return -1;
int middleIndex=(start+end)/2;
int middleData=array[middleIndex];
if(middleData==k) {
if((middleIndex>0&&array[middleIndex-1]!=k)||middleIndex==0)
return middleIndex;
else
end=middleIndex-1;
} else if(middleData>k)
end=middleIndex-1;
else
start=middleIndex+1;
return getFirstK(array, k, start, end);
}
private int getLastK(int[] array,int k, int start, int end) {
if(start>end)
return -1;
int middleIndex=(start+end)/2;
int middleData=array[middleIndex];
if(middleData==k) {
if((middleIndex<array.length-1&&array[middleIndex+1]!=k)||m
iddleIndex==array.length-1)
return middleIndex;
else
start=middleIndex+1;
} else if(middleData<k)
start=middleIndex+1;
else
end=middleIndex-1;
return getLastK(array, k, start, end);
}
}
題 面試題 39 :二叉樹的深度
題目一:輸入一棵二叉樹的根結點,求該樹的深度。從根結點到葉結點依次經過
的結點(含根、葉結點)形成樹的一條路徑,最長路徑的長度爲樹的深度。
public class Problem39 {
public static void main(String[] args) {
BinaryTreeNode root=new BinaryTreeNode();
BinaryTreeNode node1=new BinaryTreeNode();
BinaryTreeNode node2=new BinaryTreeNode();
BinaryTreeNode node3=new BinaryTreeNode();
BinaryTreeNode node4=new BinaryTreeNode();
BinaryTreeNode node5=new BinaryTreeNode();
BinaryTreeNode node6=new BinaryTreeNode();
root.leftNode=node1;
root.rightNode=node2;
node1.leftNode=node3;
node1.rightNode=node4;
node2.rightNode=node5;
node4.leftNode=node6;
root.value=1;
node1.value=2;
node2.value=3;
node3.value=4;
node4.value=5;
node5.value=6;
node6.value=7;
Problem39 p=new Problem39();
System.out.println(p.treeDepth(root));
}
public int treeDepth(BinaryTreeNode root) {
if(root==null)
return 0;
int left=treeDepth(root.leftNode);
int right=treeDepth(root.rightNode);
return (left>right)?left+1:right+1;
}
}
題目二:輸入一棵二叉樹的根結點,判斷該樹是不是平衡二叉樹。如果某二叉樹
中任意結點的左右子樹的深度相差不超過1,那麼他就是一棵平衡二叉樹。
public boolean isBalanced(BinaryTreeNode root) {
int depth=0;
return isBalanced(root,depth);
}
private boolean isBalanced(BinaryTreeNode root, int depth) {
if(root==null) {
depth=0;
return true;
}
int left=0,right=0;
if(isBalanced(root.leftNode,left)&&isBalanced(root.rightNod
e, right)) {
int diff=left-right;
if(diff<=1&&diff>=-1) {
depth=1+(left>right?left:right);
return true;
}
}
return false;
}
測試用例跟題目 1 相同。
題 面試題 40 :數組中只出現一次的數字。
題目:一個整型數組裏除了兩個數字之外,其他的數字都出現了兩次。請寫程序
找出這兩個只出現一次的數字。要求時間複雜度是 O(n),空間複雜度爲 O(1);
public class Problem40 {
public static void main(String[] args) {
int[] array= {2,4,3,6,3,2,5,5};
Problem40 p=new Problem40();
p.findNumsAppearOnce(array);
}
public void findNumsAppearOnce(int[] array) {
if(array==null)
return;
int number=0;
for(int i:array)
number^=i;
int index=findFirstBitIs1(number);
int number1=0;
int number2=0;
for(int i:array) {
if(isBit1(i,index))
number1^=i;
else
number2^=i;
}
System.out.println(number1);
System.out.println(number2);
}
private int findFirstBitIs1(int number) {
int indexBit=0;
while((number&1)==0) {
number=number>>1;
++indexBit;
}
return indexBit;
}
private boolean isBit1(int number, int index) {
number=number>>index;
return (number&1)==0;
}
}
題 面試題 41 :和爲 s 的兩個數字 VS 和爲 s 的連續正數序列
題目一:輸一個遞增排序的數組和一個數字 s,在數組中查找兩個數使得它們的
和正好是 s。如果有多對數字的和等於 s,輸出任意一對即可。例如:輸入數組
{1,2,4,7,11,15}和數字爲 15.輸出 4 和 11.
public class Problem41 {
public static void main(String[] args) {
Problem41 p=new Problem41();
int[] data= {1,2,4,7,11,15};
int sum=15;
System.out.println(p.findNumberWithSum(data, sum));
}
public boolean findNumberWithSum(int[] data,int sum) {
boolean found=false;
if(data==null)
return found;
int num1=0;
int num2=0;
int start=0;
int end=data.length-1;
while(start<end) {
int curSum=data[start]+data[end];
if(curSum==sum) {
num1=data[start];
num2=data[end];
found=true;
break;
} else if(curSum>sum)
end--;
else
start++;
}
System.out.println(num1);
System.out.println(num2);
return found;
}
}
題目二:輸入一個正數 s,打印出所有和爲 s 的連續正數序列(至少含兩個數)。
例如輸入 15,由於 1+2+3+4+5=4+5+6=7+8=15,所以結果打印出 3 個連續序列 1-5、
4-6、和 7-8.
public void findContinuesSequence(int sum) {
if(sum<3)
return;
int small=1;
int big=2;
int middle=(1+sum)/2;
int curSum=small+big;
while(small<middle) {
if(curSum==sum) {
printContineNum(small,big);
}
while(curSum>sum&&small<middle) {
curSum-=small;
small++;
if(curSum==sum)
printContineNum(small, big);
}
big++;
curSum+=big;
}
}
private void printContineNum(int small, int big) {
for(int i=small; i<=big; i++) {
System.out.print(i+" ");
}
System.out.println();
}
題 面試題 42 :翻轉單詞順序 VS 左旋轉字符串。
題目一:輸入一個英文句子,翻轉句子中單詞的順序,但單詞內字符的順序不變。
爲簡單起見,標點符號和普通字母一樣處理。例如輸入字符串“I am a student.”,
則輸出“student. a am I”.
public class Problem42 {
public static void main(String[] args) {
Problem42 p=new Problem42();
String string="I am a student.";
p.reverseSentence(string);
}
public void reverseSentence(String sentence) {
if(sentence==null)
return;
String[] str=sentence.split(" ");
StringBuffer sb=new StringBuffer();
for(int i=str.length-1; i>=0; i--) {
sb.append(str[i]+" ");
}
System.out.println(sb);
}
}
題目二:字符串的左旋轉操作是把字符串前面的若干個字符轉移到字符串的尾部。
請定義一個函數實現字符串左旋轉操作的功能。比如輸入字符串“abcdefg”和
數字 2.該函數左旋轉 2 位得到的結果“cdefgab".
public void leftRotateString(String sentence,int index){
if(sentence==null||index>sentence.length()||index<0){
return;
}
String[] splitString={sentence.substring(0,index),
sentence.substring(index,sentence.length())};
StringBuffer resultbBuffer=new StringBuffer();
for(String s:splitString){
resultbBuffer.append(reverse(s));
}
System.out.println(reverse(resultbBuffer.toString()));
}
public String reverse(String str) {
char[] array=str.toCharArray();
for(int i=0;i<(array.length+1)/2;i++)
{
char temp=array[i];
array[i]=array[array.length-1-i];
array[array.length-1-i]=temp;
}
return String.valueOf(array);
}
題 面試題 43 :n 個骰子的點數
題目:把 n 個骰子扔在地上,所有骰子朝上一面的點數之和爲 s。輸入 n,打印
出 s 的所有可能的值出現的概率。
public class Problem43 {
public static void main(String[] args) {
Problem43 p=new Problem43();
p.printProbability(2);
}
public void printProbability(int number){
if(number<1)
return;
int gMaxValue=6;
int[][] probabilities=new int[2][];
probabilities[0]=new int[gMaxValue*number+1];
probabilities[1]=new int[gMaxValue*number+1];
int flag=0;
for(int i=1;i<gMaxValue;i++){
probabilities[flag][i]=1;
}
for(int k=2;k<=number;++k){
for(int i=0;i<k;i++){
probabilities[1-flag][i]=0;
}
for(int i=k;i<=gMaxValue*k;i++){
probabilities[1-flag][i]=0;
for(int j=1;j<=i&&j<=gMaxValue;j++)
probabilities[1-flag][i]+=probabilities[flag][i-j];
}
flag=1-flag;
}
double total=Math.pow(gMaxValue, number);
for(int i=number;i<gMaxValue*number;i++){
double ratio=(double)probabilities[flag][i]/total;
System.out.print(i+" ");
System.out.println(ratio);
}
}
}
題 面試題 44 :撲克牌的順子
題目:從撲克牌中隨機抽 5 張牌,判斷是不是順子,即這 5 張牌是不是連續的。
2-10 爲數字本身,A 爲 1,J 爲 11,Q 爲 12,K 爲 13,而大小王可以看成任意的
數字。
public class Problem44 {
public static void main(String[] args) {
int[] array={0,4,6,8,0};
Problem44 test=new Problem44();
System.out.println(test.isContinuous(array));
}
public boolean isContinuous(int[] number){
if(number==null){
return false;
}
Arrays.sort(number);
int numberZero=0;
int numberGap=0;
for(int i=0;i<number.length&&number[i]==0;i++){
numberZero++;
}
int small=numberZero;
int big=small+1;
while(big<number.length){
if(number[small]==number[big])
return false;
numberGap+=number[big]-number[small]-1;
small=big;
big++;
}
return (numberGap>numberZero)?false:true;
}
}
題 面試題 45 :圓圈中最後剩下的數字
題目:0,1,...,n-1 這 n 個數排成一個圓圈,從數字 0 開始每次從這個圓圈裏
刪除第 m 個數字。求出這個圓圈裏剩下的最後一個數字。
public class Problem45 {
public static void main(String[] args) {
Problem45 p=new Problem45();
System.out.println(p.lastRemaining(6, 3));
}
public int lastRemaining(int n,int m){
if(n<1||m<1)
return -1;
int last=0;
for(int i=2;i<=n;i++){
last=(last+m)%i;
}
return last;
}
}
題 面試題 46 :求 1+2+...+n
題目:求 1+2+...+n,要求不能用除法、for、while、if、else、switch、case
等關鍵字及條件判斷語句(A?B:C)。
題 面試題 47 :不用加減乘除做加法
題目:寫一個函數,求兩個整數之和,要求在函數體內不得使用+、-、*、/四則
運算符號。
public class Problem47 {
public static void main(String[] args) {
Problem47 p=new Problem47();
System.out.println(p.add(8, 16));
}
public int add(int num1,int num2){
int sum,carray;
do{
sum=num1^num2;
carray=(num1&num2)<<1;
num1=sum;
num2=carray;
}while(num2!=0);
return num1;
}
}