Offer之路

1、題目:求 1+2+ … +n ,要求不能使用乘除法、 for 、 while 、 if 、 else 、 switch 、 case 等關鍵字以及條件判斷語句( A?B:C )。

方法1:針對循環可以用遞歸來替代。(用了if

整個代碼:

int add(int n){
if(n==1) return n;
else{
return n+add(n-1);}}

方法2:利用數學知識其實當在處理數組之類問題,利用數學知識去考慮,也是一種思路。
分析:
1+2+...+n=(n^2+n)/2,首先除以2很容易解決右移1位即可,重點在於求n^2。
n^2=n*n;將n分解成2^0,2^1,2^2,...相加的形式。例如100^2=100*100=100*(64+32+4)=100*2^6+100*2^5+100*2^2,也就是將100左移6位、5位、2位產生的3個結果分別相加即可。當然這樣的分配也不是隨機的。

#define T(X, Y, i) (Y &(1<<i)) && (X+=(Y<<i))
int foo(int n){
int r=n;
T(r, n, 0); T(r, n,1); T(r, n, 2); …T(r, n, 31);
return r >> 1;
}

//這個方法思路是將n看做是2位進制數,然後從低位到高位循環,如果當前位爲1且(假設當前位是第i位)則將n的左移i位的值進行累加。也就是利用了位操作和位操作來實現求一個數的平方。

例如:

求100的平方:

100對應的二進制爲:01100100

那麼從右邊開始向左移位(位置從0開始計數),分別發現第2,5,6位是1那麼就將100左移2,5,6之後的數累加起來,實際上是100分別乘以:2^2=4,2^5=32,2^6=64,的結果進行累加,而這個累加實質就是100*(4+32+64)=100*100也就是100的平方。但它的確沒有用到乘法,實在是妙不可言呀。

而我們要的結果是n^2+n,那麼可以在累加前將存儲累加中間結果的變量初始化爲n(比如在上面代碼中r初始爲n),這樣再進行累加就可以得到n^2+n了。

2、求二叉樹中節點最大的距離


有兩種情況,要麼是樹的深度(例如鏈表的情況),要麼是兩個子樹的深度和加2。最終的結果要麼來自某個子樹的最大距離,要麼來自兩個子樹的深度和加2。

//求樹的深度
int height(BinTree* root){
int lheight,rheight;
if(root->lchild){
lheight=1+height(root->lchild);}
if(root->rchild){
rheight=1+height(root->rchild);}
return max(lheight,rheight);
}
int maxdistance(BinTree* root){
if(root->lchild==null || root->rchild==null)
{
  return height(root);//若左子樹或者右子樹爲空,即爲樹高度
}
else{
  return height(root->lchild)+height(root->rchild)+2;  //左右子樹都不爲空時,爲左子樹與右子樹高度之和再加2
}
}

3、輸入一個已經排好序的數組和一個數字,在數組中找兩個數字,是的他們的和正好等於輸入的數字,要求時間複雜度爲O(n)。若有多對數字的和等於輸入的數字,輸出任意一對即可。

如:輸入1、2、4、7、11和15,輸出4+11=15.

分析:使用兩個指針分別從數組的起始low和終止位置high開始,若兩者之和小於輸入的值,則增加low,反之減小high。

	static void find2Numbers(int[] a,int m){
		int low=0,high=a.length-1;
		while(low<high){
			if(a[low]+a[high]<m){
				low++;
			}
			else if(a[low]+a[high]>m){
				high--;
			}
			else{
				System.out.println(a[low]+"+"+a[high]+"="+m);
				break;
			}
			}
	}

4、不使用加減乘除運算符號來實現兩個整數的加法、減法、乘法、除法

加法、減法

int A, B;
A&B   //看哪幾位有進位
A^B   //不帶進位加

將減法直接視作正數與負數相加,而計算機中負數直接取其正數的補碼,即和加法操作一樣。

	static int Add(int a, int b)
	{
	    int sum = a ^ b;
	    int carry = a & b;
	    while (carry != 0) {
	        a = sum;
	        b = carry << 1;
	        sum = a ^ b;
	        carry = a & b;
	    }

	    return sum;
	}

乘法

如果可以使用“+”,題1中的解法即可。




發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章