其它算法

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/yanyingnan1357/article/details/80350060

其它算法练习

圆圈中最后剩下的数字

package neu.yanyingnan.offer;

import java.util.LinkedList;
            /*题目描述
            每年六一儿童节,牛客都会准备一些小礼物去看望孤儿院的小朋友,今年亦是如此。
            HF作为牛客的资深元老,自然也准备了一些小游戏。其中,有个游戏是这样的:
            首先,让小朋友们围成一个大圈。然后,他随机指定一个数m,让编号为0的小朋友开始报数。
            每次喊到m-1的那个小朋友要出列唱首歌,然后可以在礼品箱中任意的挑选礼物,并且不再回到圈中,
            从他的下一个小朋友开始,继续0...m-1报数....这样下去....直到剩下最后一个小朋友,
            可以不用表演,并且拿到牛客名贵的“名侦探柯南”典藏版(名额有限哦!!^_^)。
            请你试着想下,哪个小朋友会得到这份礼品呢?(注:小朋友的编号是从0到n-1)*/
public class Solution_46 {
/*    public int LastRemaining_Solution(int n, int m) {//方法一 :链表法 时间复杂度O(mn) 空间 O(n)
        LinkedList<Integer> list = new LinkedList<Integer>();//用链表模拟删除过程
        for(int i=0; i<n; i++)//将编号加入链表
            list.add(i);
        int del = 0;//记录要删除的下标,初始为零
        while(list.size()>1){
            del = (del+m-1)%list.size();//这句话是核心 在原来的del位置基础上再加m-1 % 起到了循环的效果
            list.remove(del);
        }
        return list.size()==1? list.get(0): -1;
    }*/
   /* public int LastRemaining_Solution(int n, int m) {//方法二 :递推公式循环法 时间复杂度O(n) 空间 O(1)
        if (m < 1 || n < 1)  //递推公式:f[1,m]=0;(n=1)      f[n,m]=(f[n-1,m]+m)%n;(n>1)
            return -1;  
        int last = 0;         
        for (int i = 2; i <= n; i++) // i代表人数,直到循环到人数n 
            last = (last + m) % i;  
        return last; 
    }*/
    public int LastRemaining_Solution(int n, int m) {//方法三:递推公式递归法 时间复杂度O(n) 空间 O(1)
        if(m<1 || n<1)
            return -1;
        else{
            if (n==1)  //递推公式:f[1,m]=0;(n=1)        f[n,m]=(f[n-1,m]+m)%n;(n>1)
                return 0;            
            return (LastRemaining_Solution(n-1, m)+m) % n; 
        }
    }
}

扑克牌的顺子

package neu.yanyingnan.offer;

import java.util.Arrays;
            /*题目描述
            LL今天心情特别好,因为他去买了一副扑克牌,发现里面居然有2个大王,2个小王(一副牌原本是54张^_^)...
            他随机从中抽出了5张牌,想测测自己的手气,看看能不能抽到顺子,如果抽到的话,他决定去买体育彩票,嘿嘿!!
            “红心A,黑桃3,小王,大王,方片5”,“Oh My God!”不是顺子.....LL不高兴了,
            他想了想,决定大\小 王可以看成任何数字,并且A看作1,J为11,Q为12,K为13。
            上面的5张牌就可以变成“1,2,3,4,5”(大小王分别看作24),“So Lucky!”。
            LL决定去买体育彩票啦。 现在,要求你使用这幅牌模拟上面的过程,然后告诉我们LL的运气如何。
            为了方便起见,你可以认为大小王是0。*/
public class Solution_45 {
/*    public boolean isContinuous(int [] numbers) {
        if(numbers == null || numbers.length != 5)
            return false;
        Arrays.sort(numbers);//第一步:排序

        if(numbers[numbers.length-2]==0)//如果排好序的数组中倒数第二个数为零,那么一定可以连续
            return true;

        int zero = 0;
        int gap = 0;

        for(int i=0; i<numbers.length-1; i++){
            if(numbers[i]==0)//第二步:统计0的个数
                zero++;
            else{
                if(numbers[i] == numbers[i+1])//若有相等 一定不能有连续的结果
                    return false;
                else{
                    gap += (numbers[i]-i)-(numbers[i+1]-(i+1));//第三步:统计间隔
                }
            }
        }
        if(Math.abs(gap)==zero)
            return true;
        else
            return false;
    }*/

    // 考略到顺子的特性,最大值和最小值之差绝对为4,  
    // 然而又有大小王的存在,所以a[4]-a[index] <=4  
    // 此题关键是去重和0的个数,还有最大最小的差值  
    public boolean isContinuous(int[] numbers) {  
        if (numbers == null || numbers.length != 5)  
            return false;  
        Arrays.sort(numbers); 

        if(numbers[numbers.length-2]==0)//如果排好序的数组中倒数第二个数为零,那么一定可以连续
            return true;

        // 大小王看成0,最多4个  
        // index为0的个数,也是第一个不为0的数字下标  
        int index = 0;  
        while (numbers[index] == 0)  
            index++;  
        for (int i = index; i < numbers.length - 1; i++){  
            // 判断有没有重复扑克  
            if (numbers[i] == numbers[i + 1])  
                return false;  
        }
        return numbers[4] - numbers[index] <= 4;  //最大最小值差值   这个思路 比我的思路叼一点!
    }  
}

(完成)菲波那切数列

            /*题目描述:
              大家都知道斐波那契数列,现在要求输入一个整数n,请你输出斐波那契数列的第n项。n<=39*/
public class Solution_07 {
    public int Fibonacci(int n) {//这是迭代法  时间效率为O(n)
                                    //可以用递归  代码超级简单 效率不好 面试不能过
        if(n < 2)
            return n;

        int f0 = 0;
        int f1 = 1;
        int tmp = 0;//一定要引入tmp;
        for(int i=2; i<=n; i++){
            tmp = f1;
            f1 = f0 + f1;
            f0 = tmp;
        }
        return f1;
    }

(完成)跳台阶

            /*题目描述
            一只青蛙一次可以跳上1级台阶,也可以跳上2级。求该青蛙跳上一个n级的台阶总共有多少种跳法。*/
public class Solution_08 {
    public int JumpFloor(int target) {//只是把菲波那切数列现实化
        if(target < 3)
            return target;

        int f1 = 1;
        int f2 = 2;
        int tmp;
        for(int i=3; i<=target; i++){
            tmp = f2;
            f2 = f1 + f2;
            f1 = tmp;
        }
        return f2;
    }
}

(完成)变态跳台阶

            /*题目描述
            一只青蛙一次可以跳上1级台阶,也可以跳上2级……它也可以跳上n级。求该青蛙跳上一个n级的台阶总共有多少种跳法。*/
public class Solution_09 {
    public int JumpFloorII(int target) {    //共有2^(n-1)中跳发
        //return (int) Math.pow(2,target-1);//太low
        return 1<<target-1;//减号优先级更高  所以不加括号
    }
}

(完成)矩形覆盖

            /*题目描述
            我们可以用2*1的小矩形横着或者竖着去覆盖更大的矩形。
            请问用n个2*1的小矩形无重叠地覆盖一个2*n的大矩形,总共有多少种方法?*/
public class Solution_10 {
    public int RectCover(int target) {
        if(target < 3)
            return target;

        int f1 = 1;
        int f2 = 2;
        int tmp;
        for(int i=3; i<=target; i++){
            tmp = f2;
            f2 = f1 + f2;
            f1 = tmp;
        }
        return f2;
    }
}

完成求解一个数的整数次方

            /*题目描述
            给定一个double类型的浮点数base和int类型的整数exponent。求base的exponent次方。*/
public class Solution_12 {
    public static double Power(double base, int exponent) {
        if(equal(base,0.0) && exponent<=0)                  //四中情况要考虑全面
            throw new RuntimeException("0的0或负数次幂没有意义"); 
        if(exponent == 0){                                                  
            return 1.0;                             
        }       

        double res;
        if(exponent>0){
            res = UpPower(base,exponent);
        }else{
            res = UpPower(1.0/base,-exponent);
        }
        return res;
    }

/*    private static double UpPower(double base,int exponent){//这是一个全面不够高效的解法,
        double res = 1.0;
        for(int i=1; i<=exponent;i++){
                res*=base;
        }
        return res;
    }*/

    private static double UpPower(double base,int exponent){
        if(exponent == 0){
            return 1;
        }
        if(exponent == 1){
            return base;
        }
        double res = UpPower(base, exponent>>1);//n为偶数时:a^n=a^n/2 * a^n/2;n为奇数,a^n=(a^(n-1)/2)* (a^(n-1/2))* a      
        res*=res;                               //所以对乘法处进行优化,如果是32次方,等于16次方*16次方
        if((exponent & 1)==1)//if(exponent%2==1)求余的高效方法 //所以有时候递归反而优化了算法
            res*=base;
        return res;
    }

    private static boolean equal(double num1,double num2){//注意:由于计算机表示小数(包括float和double型小数)都有误差,我们不能直接用==判断两个小数是否相等,
        if(Math.abs(num1 - num2)<0.0000001)
            return true;
        return false;
    }
}
阅读更多
想对作者说点什么?

博主推荐

换一批

没有更多推荐了,返回首页