剑指offer

 
/**
 * Created by zhang on 2018/6/25.
 * https://blog.csdn.net/abc7845129630/article/details/52823565
   写一个函数,求两个整数之和,要求在函数体内不得使用+、-、*、/四则 运算符号。
 */

public class AddMethod {
    public int addMethod(int num1,int num2){
        int sum=0;
        int carry=0;
        do{
             sum=num1^num2;
             carry=(num1&num2)<<1;
             num1=sum;
             num2=carry;

        }while(num2!=0);
        return num1;
    }
    public static void main(String[] args) {
        AddMethod add = new AddMethod();
        int result=add.addMethod(8,10);
        System.out.println(result);
    }
}
^异或运算与&按位与运算。
 
/**
 * Created by zhang on 2018/6/26.
 * 求1+2+...+n,要求不能使用乘除法、for、while、if、else、switch、case等关键字以及条件判断语句(A? B:C)
 */
public class Accumulation {
    public int sum(int n)
    {
        try
        {
            return n+sum(n-1);
        }
        catch(Exception e)
        {
            return 1;

        }
    }

    public static void main(String[] args) {
        Accumulation  accumulation= new Accumulation();
        int add=accumulation.sum(100);
        System.out.println(add);
    }
}
 
/**
 * Created by zhangli on 2018/6/26.
 *输入一个英文句子,翻转句子中单词的顺序,但单词内字符的顺序不变。
 * 为简单起见,标点符号和普通字母一样处理。
 * 例如输入字符串“I am a student.”, 则输出“student. a am I”
 */
public class ReverseSentence {
    public void reverseSentence(String sentence){
        if(sentence==null){
            return;
        }
         String[] str = sentence.split(" ");
         int length = str.length;
         StringBuffer newString = new StringBuffer();

        for(int i=length-1;i>=0;i--){
            if(i==0){
                newString.append(str[i]);
            }else {
                newString.append(str[i]+" ");
            }
        }
        System.out.println(newString);

    }

    public static void main(String[] args) {
         ReverseSentence Sentence = new ReverseSentence();
        Sentence.reverseSentence("I am a student.");
    }
}
 
/**
 * 题目:0,1,...,n-1这n个数排成一个圆圈,从数字0开始每次从这个圆圈里删除第m个数字。求出这个圆圈里剩下的最后一个数字。
 */
                     0                           n=1 
    f(n,m)={ 
                [f(n-1,m)+m]%n          n>1 
public class LastNumOfCircle { public int lastNumOfCircle(int n,int m){ if(n<1||m<1){ return -1; } int lastNum=0; for (int i = 2; i <n; i++) { lastNum=(lastNum+m)%i; } return lastNum; } public static void main(String[] args) { LastNumOfCircle lastNumOfCircle = new LastNumOfCircle(); int last=lastNumOfCircle.lastNumOfCircle(4,3); System.out.println(last); } }
题目:从扑克牌中随机抽5张牌,判断是不是顺子,即这5张牌是不是连续的。2-10为数字本身,A为1,J为11,Q为12,K为13,而大小王可以看成任意的数字。
 
解析:/**
 * 我们需要把扑克牌的背景抽象成计算机语言。不难想象,我们可以把5张牌看成由5个数字组成的数组。大小王是特殊的数字,
 * 我们不妨把它们都当成0,这样和其他扑克牌代表的数字就不重复了。接下来我们来分析怎样判断5个数字是不是连续的。最
 * 直观的是,我们把数组排序。但值得注意的是,由于0可以当成任意数字,我们可以用0去补满数组中的空缺。也就是排序之
 * 后的数组不是连续的,即相邻的两个数字相隔若干个数字,但如果我们有足够的0可以补满这两个数字的空缺,这个数组实
 * 际上还是连续的。举个例子,数组排序之后为{0,1,3,4,5}。在1和3之间空缺了一个2,刚好我们有一个0,也就是我们
 * 可以它当成2去填补这个空缺。于是我们需要做三件事情:把数组排序,统计数组中0的个数,统计排序之后的数组相邻数
 * 字之间的空缺总数。如果空缺的总数小于或者等于0的个数,那么这个数组就是连续的;反之则不连续。最后,我们还需要
 * 注意的是,如果数组中的非0数字重复出现,则该数组不是连续的。换成扑克牌的描述方式,就是如果一副牌里含有对子,则不可能是顺子。
 */
public class Poker {
    public static void main(String[] args) {
        int[] array={0,0,4,7,8};
        Poker test=new Poker();
        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++) {  //求出0的个数,即王牌的个数
            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;     //如果总间隔数大于0的个数则是错误的
    }
}
题目描述:把一个数组最开始的若干个元素搬到数组的末尾,我们称之为数组的旋转。输入一个递增排序的数组的一个旋转,输出旋转数组的最小元素。例如数组{3,4,5,1,2}为{1,2,3,4,5}的一个旋转,该数组的最小值为1.

 分析: 首先我们用两个指针,分别指向数组的第一个元素和最后一个元素。按照题目旋转的规则,第一个元素应该是大于或者等于最后一个元素的(这其实不完全对,还有特例。后面再讨论特例)。 
接着我们得到处在数组中间的元素。如果该中间元素位于前面的递增子数组,那么它应该大于或者等于第一个指针指向的元素。此时数组中最小的元素应该位于该中间元素的后面。我们可以把第一指针指向该中间元素,这样可以缩小寻找的范围。同样,如果中间元素位于后面的递增子数组,那么它应该小于或者等于第二个指针指向的元素。此时该数组中最小的元素应该位于该中间元素的前面。我们可以把第二个指针指向该中间元素,这样同样可以缩小寻找的范围。我们接着再用更新之后的两个指针,去得到和比较新的中间元素,循环下去。 

         按照上述的思路,我们的第一个指针总是指向前面递增数组的元素,而第二个指针总是指向后面递增数组的元素。最后第一个指针将指向前面子数组的最后一个元素,而第二个指针会指向后面子数组的第一个元素。也就是它们最终会指向两个相邻的元素,而第二个指针指向的刚好是最小的元素。这就是循环结束的条件。 

public class RevertNumber {

 
    public static void main(String[] args) {
        RevertNumber p8=new RevertNumber();
       // int[] array={1,0,1,1,1};
        int[] array={3,4,5,1,2};
        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]==array[mid]){
                if(array[leftIndex+1]!=array[rightIndex-1]){         //针对于{1,0,1,1,1};这种情况第一个不相等的地方可见分晓
                    mid=array[leftIndex+1]<array[rightIndex-1]?(leftIndex+1):(rightIndex-1);
                    break;
                }else{
                    leftIndex++;
                    rightIndex--;
                }
            }else{
                if(array[mid]>=array[leftIndex])
                    leftIndex=mid;
                else {
                    if(array[mid]<=array[rightIndex])
                        rightIndex=mid;
                }
            }
        }
        return array[mid];
    }
}
写一个函数,输入n,求斐波那契数列的第n项
 
public class Fibonacci {
    public int fibonacci(int n){
        if(n==0||n==0) {
            return 1;
        }else{
            return fibonacci(n-1)+fibonacci(n-2);
        }
    }
    public static void main(String[] args) {
        Fibonacci fi = new Fibonacci();
        System.out.println(fi.fibonacci(15));

    }
}
请实现一个函数,输入一个整数,输出该数二进制表示中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;
        }
    }

 

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值