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中的解法即可。




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