剑指Offer相关内容(7-12)

剑指offer程序题设计相关的知识点(Java语言)

7.斐波那契数列

  大家都知道斐波那契数列,现在要求输入一个整数n,请你输出斐波那契数列的第n项(从0开始,第0项为0)。n<=39。【知识点:递归】

  注意
   1.斐波那契数列(Fibonacci sequence),又称黄金分割数列、因数学家列昂纳多·斐波那契(Leonardoda Fibonacci)以兔子繁殖为例子而引入,故又称为“兔子数列”,指的是这样一个数列:1、1、2、3、5、8、13、21、34、……在数学上,斐波纳契数列以如下被以递推的方法定义:F(1)=1,F(2)=1, F(n)=F(n-1)+F(n-2)(n>=3,n∈N*),当前的数字等于前两项的和。考虑以下三种情况。

	    public class Solution {
	        public int Fibonacci(int n) {
	            if(n<0){
	                return 0;
	            }else if(n < 2){
	                return n;
	            }else{
	                int sum = 0;
	                int n1 = 0;
	                int n2 = 1;
	                for(int i=2;i<=n;i++){
	                    sum = n1 + n2;
	                    n1 = n2;
	                    n2 = sum;
	                }
	                return sum;
	            }
	        }
	    }

9.跳台阶

  一只青蛙一次可以跳上1级台阶,也可以跳上2级。求该青蛙跳上一个n级的台阶总共有多少种跳法(先后次序不同算不同的结果)。【知识点:递归】

  注意
   1.该问题实质是斐波那契数列求和,递推公式为 f(n)=f(n-1)+f(n-2)。假设,一级台阶,有f(1)种方法,二级有f(2)种,以此类推,n级有f(n)种方法。显然,f(1)=1;f(2)=2。假设n级台阶,第一步就有两种情况,跳一步或跳两步。如果跳一步,剩下的就是f(n-1);如果跳两步,剩下的就是f(n-2)。所以总数是f(n)=f(n-1)+f(n-2)。

   public class Solution {
        public int JumpFloor(int C) {
            if(C<=0){
                return 0;
            }
            if(C==1||C==2){
                return C;
            }else{
                return JumpFloor(C-1)+JumpFloor(C-2);
            }
        }
    }

8.变态跳台阶

  一只青蛙一次可以跳上1级台阶,也可以跳上2级……它也可以跳上n级。求该青蛙跳上一个n级的台阶总共有多少种跳法。【知识点:贪心】

  注意
   1.非递归:如果有n级阶梯,对于第n级,青蛙一定会停留,但是对于中间的n-1级阶梯,青蛙有可能停或者不停,两种情况,于是,结果就有2^(n-1)种可能。

    public class Solution {
        public int JumpFloorII(int target) {
            if(target<=0){
                return 0;
            }else{
                //int a = 1; //实现一个递归求2的次方
                //for(int i=1;i<target;i++){
                    //a = a*2;
                //}
                //return a;
                return (int)Math.pow(2,target-1);
            }
        }
    }

   2.斐波那契:到达1级台阶只有一种可能,到达2级台阶有两种可能,所以f(1)=1,f(2)=2。要达到3级台阶,可以在1级起跳,也可以在2级起跳,所以需要到达1级台阶的可能情况+到达2级台阶的可能情况+f(0),所以f(3)=f(2)+f(1)+1。同理,到达n级台阶,可以在n-1、n-2、n-3…级起跳,f(n)=f(n-1)+f(n-2)+f(n-3)+...+1。如果:

f(n)=f(n-1)+f(n-2)+f(n-3)...+f(n-n)=f(0)+f(1)+f(2)+...+f(n-1)

f(n-1)=f(0)+f(1)+..f(n-2)

上式-下式=f(n)-f(n-1)=f(n-1),所以f(n)=2*f(n-1)

    public class Solution {
        public int JumpFloorII(int target) {
            if(target==0){
                return 0;
            }
            if(target==1){
                return 1;
            }else{
                return 2*JumpFloorII(target-1);
            }
        }
    }

9.矩形覆盖

  我们可以用2x1的小矩形横着或者竖着去覆盖更大的矩形。请问用n个2x1的小矩形无重叠地覆盖一个2xn的大矩形,总共有多少种方法?【知识点:递归】

  注意
   1.依然是斐波那契的应用: 如果n=1,只有一种竖着的摆放方式;如果n=2,则有两个竖着、两个横着(上下)两种方式;如果n>2,(1).第一个竖着放,剩下的有f(n-1)种方式;(2).第一个横着放,则下面的的那个也要横着放,已经是确定的,所以还剩下f(n-1)种方式。

    public class Solution {
        public int RectCover(int target) {
            if(target<=0){
                return 0;
            }
            if(target==1||target==2){
                return target;
            }else{
                return RectCover(target-1)+RectCover(target-2);
            }
        }
    }

10.二进制中1的个数

  输入一个整数,输出该数二进制表示中1的个数。其中负数用补码表示。【知识点:进制转化、补码反码原码】

  注意
   1.用方法将整数转为二进制数,统计其中1的个数。(更快,内存占用更少)

    public class Solution {
        public int NumberOf1(int n) {
            int num = 0;
            String str = Integer.toBinaryString(n);
            char[] chars = str.toCharArray();
            int i = 0;
            for(;i<str.length();i++){
                if(chars[i] == '1'){
                    num++;
                }
            }
            return num;
        }
    }

   2.用位运算,将1每次左移,和数字进行&运算,如果成功,则返回1.。

    public class Solution {
        public int NumberOf1(int n) {
			int index = 1;
			int num = 0;
			while(index!=0){
				if((n&index)!=0){
				   num++;
				}
				index = index<<1;
			}
			return num;
        }
    }

11.数值的整数次方

  给定一个double类型的浮点数base和int类型的整数exponent。求base的exponent次方。保证base和exponent不同时为0。【知识点:数学】

  注意
   1.直接调用数学方法。

    public class Solution {
        public double Power(double base, int exponent) {
            if(base==0&&exponent==0){
                return 0;
            }else{
                return Math.pow(base, exponent);
            }
      }
    }

12.调整数组顺序使奇数位于偶数的前面

  输入一个整数数组,实现一个函数来调整该数组中数字的顺序,使得所有的奇数位于数组的前半部分,所有的偶数位于数组的后半部分并保证奇数和奇数,偶数和偶数之间的相对位置不变。【知识点:数组】

  注意
   1.。第一种方法,创建一个和原数组长度一样的新数组,第一次遍历原数组,将奇数存入新数组,第二次遍历原数组,将偶数存入原数组,在将新数组的值赋值给原数组。在赋值的时候,如果使用array = newarr;并不是正确赋值,这会改变array的内存地址,但是在主函数中操作的是原array,在方法中使用以上语句赋值,在主函数中没有作用,导致array并不会发生变化。所以应该用循环赋值,仅仅将新数组的值赋值给原数组,地址不参与其中,这样,改变的就是原来的数组,在主函数中输出的就是排序的数组。(更快,内存占用更少)

public class Jz_12_sortarraybasejo {
    public void reOrderArray(int [] array) {
        int[] newarr = new int[array.length];
        int j = 0;
        for(int i =0;i<array.length;i++){
            if(array[i]%2!=0){
                newarr[j] = array[i];
                j++;
            }
        }
        for(int i =0;i<array.length;i++){
            if(array[i]%2==0){
                newarr[j] = array[i];
                j++;
            }
        }
//        array = newarr;  
        
        for(int i=0;i<array.length;i++) {
        	array[i] = newarr[i];
		}
    }
	public static void main(String[] args) {
		// TODO Auto-generated method stub
		Jz_12_sortarraybasejo jz = new Jz_12_sortarraybasejo();
		int[] array = {1,2,3,4,5,6,7};
		for(int i=0;i<array.length;i++) {
			System.out.print(array[i]);
		}
		System.out.println('\n');
		
		jz.reOrderArray(array);
		System.out.println('\n');
		
		for(int i=0;i<array.length;i++) {
			System.out.print(array[i]);
		}
	}

   2.第二种方法,参考冒泡排序的思想,从头遍历数组,只要是遇到偶数在奇数前面的情况,就交换两个数。

    public class Solution {
        public void reOrderArray(int [] array) {
            for(int i =0;i<array.length;i++){  //大循环
                //每次都从头开始 针对前面有连续偶数的情况
                for(int j=0;j<array.length-1;j++){
                    if(array[j]%2==0&&array[j+1]%2!=0){
                        int temp = array[j];
                        array[j] = array[j+1];
                        array[j+1] = temp;
                    }
                }
            }
        }
    }

   3.第三种方法。

用两个下标odd,even,even遍历数组,遇到偶数继续往后走,遇到奇数就将该奇数赋给odd对应位置,然后odd往后移动(先将从odd开始的位置的所有元素往后挪动一个,这样做的目的是能够保持偶数相对位置不变)。这个思路也就是使得odd前面的都是奇数,而且相对位置不变,而odd与even之间的都是偶数,然后even遇到奇数停下来,并将其放到odd位置,并且前提是将odd位置上的偶数向后挪动保证偶数相对位置不变,这样当even走到最后时,就使得odd之前的都是奇数,odd与even之间的都是偶数。
———————————————— 版权声明:本文为CSDN博主「lyl194458」的原创文章,遵循CC 4.0
by-sa版权协议,转载请附上原文出处链接及本声明。
原文链接:https://blog.csdn.net/lyl194458/article/details/89714872

    public class Solution {
        public void reOrderArray(int [] array) {
            int len = array.length;
            int odd = 0;
            int even = 0;
            while(even<len){
                if(array[even]%2!=0){
                    int temp = array[even];
                    for(int i=even;i>odd;i--){
                        array[i] = array[i-1];
                    }
                    array[odd] = temp;
                    even++;
                    odd++;
                }else{
                    even++;
                }
            }
        }
    }
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值