剑指offer2.2

1.不用加减乘除做加法

思路: 1.不进位加法:异或 a^b

2.进位加法:与+左移1 a&b<<1

3.直到进位的为0为止

public class Solution {
    public int Add(int num1,int num2) {
        if(num1==0)  return num2;
         if(num2==0)  return num1;
        int result=0; int carry=0;
        while(num2!=0){
            result=num1^num2;
            carry=(num1&num2)<<1;
            num1=result;
            num2=carry;
        }
        return result;}}

2. 二进制中1的个数

1)除2取模法

2)二进制移位法

       直接将整数看成二进制,然后采用移位的方法。让一个数0x01从右向左与val的每一位进行&操作来判断

//超时,所以不妨找到最右边的1   
public int NumberOf1(int n) {
        int val=1; int count=0;
        while(n!=0){
            if((val & n)!=0) count=count+1;
               val=val<<1;
        }
      return count;
    }}

3)2)的进阶,找到最右边的1

       思路:n-1会使得最右边1变0,最右边1右边的0变1

                 再对其进行运算,最右边1会变成0,能做多少次这种运算即证明有多少个1

    public int NumberOf1(int n) {
        int count=0;
        while(n!=0){
            n=n&(n-1);
             count++;
        }
      return count;}

 3.数值的整数次方

 //不如用快速幂法
    public double Power(double base, int exponent) {
         if(exponent==0)    return 1;
          double a=p(base,exponent);
          if(exponent>0)  return a;
            else return 1/a;
   }
    public double p(double base, int exponent) {
        if(base==0)        return 0;
        if(exponent==0)    return 1;
        double result=1; exponent=Math.abs(exponent);//这里exponent一定要为绝对值
        while(exponent!=0){
              if(exponent%2==1)  result=result*base;
               base=base*base;
               exponent=exponent/2;
                         }
        return result;
       }
      

4.数组中只出现一次的两个数字

一个整型数组里除了两个数字只出现一次,其他的数字都出现了两次。请写程序找出这两个只出现一次的数字。
要求:空间复杂度 O(1),时间复杂度 O(n)

思路:位运算异或(^)

/*1.利用a^b^a=b来计算数组,最终留下c^d的值(cd只出现一次),^(异或)
2.找出cd不相等的位数:ca异或的话,相等为0,不等为1,那么用&1不断向左判断找不为0的数即可
3.根据这个不相等的位数可以把数组分成两组了
*/

import java.util.*;
public class Solution {
    public int[] FindNumsAppearOnce (int[] array) {
            int temp=0;
            for(int mask:array){
                temp=temp^mask;
            }
            int num=1;
            while((num&temp)==0){
                num=num<<1;
            }
           //开始把数组分成两组
        int a=0; int b=0;
        for(int mask:array){
            if((mask&num)==0) a=a^mask;
            else b=b^mask;
            }
        if(a>b){//位运算交换
            a=a^b;
            b=b^a;
            a=a^b;
        }
         return new int[]{a,b};    
    }
}

5.求1+2+3+...+n

求1+2+3+...+n,要求不能使用乘除法、for、while、if、else、switch、case等关键字及条件判断语句(A?B:C)。

思路:  1.求和公式
             2.循环求和
             3.递归
             4.短路求值(修改递归)
      作为"&&"和"||"操作符的操作数表达式,这些表达式在进行求值时,只要最终的结果已经可以确定是真或假, 求值过程便告终止,这称之为短路求值。
 
  假如expr1和expr2都是表达式,并且expr1的值为0,在下面这个逻辑表达式的求值过程中:
    expr1 && expr2 expr2将不会进行求值,因为整个逻辑表达式的值已经可以确定为0。
    expr1的值为1, expr1 || expr2 expr2将不会进行求值,因为整个逻辑表达式的值已经确定为1。
  因此可以利用左边的表达式来作为递归结束的判断条件。因此递归的表达式就在右边了。而想到递归的解法,必然是sum=Sum(n)=Sum(n-1)+n
        使用&&,结束条件在左边,只能是n=0时结束,即从n递减到0结束,
        由于左边需要不断的进行条件判断,因为需要一个每次递归后都递减的变量,而n是递减的,因此用n来作为左边的变量,int sum = n;
        而短路求值左边可以写为(n>0)或(n!=0),右边写为sum +=sum(n-1),再加一个判断(实际上需要保证右边的条件一直为真),因此java版的解法就出来了.
    */
    


   public int Sum_Solution(int n) {
        int sum=n;
       boolean c=(n!=0)&&((sum+=Sum_Solution(n-1))>0);
        return sum;
    }

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值