• 剑指Offer系列之题46~题50


    46.扑克牌顺子

    从扑克牌随机抽5张牌,判断是不是一个顺子,即这5张牌是不是连续的。2~10为数字本身,A为1,J为11,Q为12,K为13,而大、小王可以看成任意数字。

    找出最大最小值,0的数量,判断最大最小值的差中的空缺数是否小于等于0的个数


    1.快排:

    快排超时,使用Arrays.sort(numbers);

    public class Solution {
        public boolean isContinuous(int [] numbers) {
            //大、小王=任意数字 A=1 J=11 Q=12 K=13  可以认为大小王是0
            //5张牌 可能是无序的
            if(numbers.length<1)
                return false;
            int diff=0;//数字之间的空缺
            int count=0;//大小王的数量
            quickSort(numbers,0,numbers.length-1);
            for(int i=0;i<numbers.length-1;++i){
                if(numbers[i]==0){//大小王的数量
                    count++;
                }else{
                    if(numbers[i+1]==numbers[i]){//两者相等则不连续
                        return false;
                    }//差-1即两数字间空缺数字的数量
                    diff+=numbers[i+1]-numbers[i]-1;
                }
            }
            if(diff<=count)//若空缺数字的数量小于大小王的个数
                return true;
            return false;
    
        }
        //快速排序
        public void quickSort(int a[],int low,int high){
            if(low<high){
                int index=partition(a,low,high);
                quickSort(a,low,index-1);
                quickSort(a,index+1,high);
            }
        }
        public int partition(int a[],int low,int high){
            int temp=a[low];
            while(low<high){
                while(low<high && a[high]>temp)
                    high--;
                a[low]=a[high];
                while(low<high && a[low]<temp)
                    low++;
                a[high]=a[low];
            }
            a[low]=temp;
            return low;
        }
    }
    

    2.找出最大最小值,计算差值:

    public class Solution {
        public boolean isContinuous(int [] numbers) {
            //大、小王=任意数字 A=1 J=11 Q=12 K=13  可以认为大小王是0
            //5张牌 可能是无序的
            if(numbers.length<1)
                return false;
            int count=0;//大小王的数量
            int max=-1;
            int min=14;
            int a[]=new int[5];//存储已出现的数字
            int j=0;
            for(int i=0;i<numbers.length;++i){
                if(numbers[i]==0){
                    count++;
                }else{
                    //遍历查看该数字是否已出现过
                    for(int k=0;k<5;++k){
                        if(a[k]==numbers[i])//已出现则返回false
                            return false;
                    }
                    if(numbers[i]<min)
                        min=numbers[i];
                    if(numbers[i]>max)
                        max=numbers[i];
                    a[j]=numbers[i];
                    j++;
                }
    
            }
            int diff=max-min-(numbers.length-count-1);
            return diff<=count;
        }
    
    }
    

    47.圆圈中最后剩下的数

    0,1,…,n-1这n个数字排成一个圆圈,从数字0开始,每次从这个圆圈里删除第m个数字,求出这个圆圈里剩下的最后一个数字。

    约瑟夫环。找到规律然后递归/循环;利用循环链表

    [约瑟夫环的公式: f(n,m)= egin{cases} 0, &n=1\ [f(n-1,m)+m]\%n, &n>1 end{cases} ]


    1.循环:

    public class Solution {
        public int LastRemaining_Solution(int n, int m) {
            //约瑟夫环
            if(n<=0 || m<=0)//错误输入
                return -1;
            int last=0;
            for(int i=2;i<=n;++i){//公式
                last=(last+m)%i;
            }
            return last;
        }
    }
    

    2.递归:

    public class Solution {
        public int LastRemaining_Solution(int n, int m) {
            //约瑟夫环
            if(n<=0 || m<=0)//错误输入
                return -1;
            if(n==1)
                return 0;
            return (LastRemaining_Solution(n-1,m)+m)%n;
        }
    }
    

    3.循环链表:

    数组模拟环。考虑每个变量的作用,考虑环如何表达等因素。

    public class Solution {
        public int LastRemaining_Solution(int n, int m) {
            //约瑟夫环
            //错误输入
            if(n<=0 || m<=0)
                return -1;
            int temp[]=new int[n];//辅助数组,存储元素
            int i=-1,step=0,count=n;//i为索引,step为走的步数(m),count为剩余的数量
            while(count>0){
                i++;
                if(i>=n)//模拟环,当到达末尾时,从头开始
                    i=0;
                if(temp[i]==-1)//若为-1,证明已删除
                    continue;
                step++;
                if(step==m){//走了m步,删除该元素(置-1),总数减一,步数重置为0
                    temp[i]=-1;
                    step=0;
                    count--;
                }
            }
    
            return i;//返回跳出循环时i的值,即最后一个数字的索引
        }
    }
    

    48.求1+2+3…+n

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

    当这些操作不可用时,可以考虑短路操作当作递归退出条件。


    短路+递归:

    &&||都可以

    public class Solution {
        public int Sum_Solution(int n) {
            //利用短路操作 &&
            int sum=n;
            boolean flag=(n>0)&& ((sum+=Sum_Solution(n-1))>0);//若n小于等于0则不进行后面的操作
            return sum;
        }
    }
    

    49.不用加减乘除做加法

    写一个函数,求两个整数之和,要求在函数体内不得使用+、-、*、/四则运算符号。

    利用位运算。其中异或得到没有进位时的和,得到都为1的位,与左移一位得到进位,最后相加(直到没有进位时)得到和。


    1.位运算:

    public class Solution {
        public int Add(int num1,int num2) {
            //三步走 先得到不进位的结果,然后得到进位,最后相加
            if(num1==num2)//相等则左移一位 即*2
                return num1<<1;
    
            while(num2!=0){//若仍存在进位,继续进行运算
                int p1=num1^num2;//step 1 异或运算得到没有进位时的和
                int p2=(num1&num2)<<1;//step 2  与运算找到都为1的位,然后左移一位得到进位
                num1=p1;
                num2=p2;
            }
            return num1;
        }
    }
    

    50.把字符串转换成整数

    将一个字符串转换成一个整数,要求不能使用字符串转换整数的库函数。 数值为0或者字符串不是一个合法的数值则返回0

    输入描述:输入一个字符串,包括数字字母符号,可以为空

    输出描述:如果是合法的数值表达则返回该数字,否则返回0

    遍历,依次相加组成结果。中间需要注意越界,符号等因素


    1.遍历:

    public class Solution {
        public int StrToInt(String str) {
            if(str==null || str.equals("")||str.equals(" "))//异常输入
                return 0;
            str=str.trim();//去首尾空格
            boolean flag=true;//正负标志
            if(str.charAt(0)=='-'){
                flag=false;
                str=str.substring(1,str.length());
            }else if(str.charAt(0)=='+'){
                str=str.substring(1,str.length());
            }
            long res=0;//long表达,防止越界
            for(int i=0;i<str.length();++i){
                char c=str.charAt(i);
                if(c<48 || c>57)//若不是纯数字
                    return 0;
                res+=(c-'0')*Math.pow(10,str.length()-i-1);//转化为整型
            }
    
            if(!flag){//添加符号
                res= -res;
            }
    
            if(res>Integer.MAX_VALUE || res<Integer.MIN_VALUE)//判断是否越界
                return 0;
    
            return  (int)res;
    
        }
    }
    

    如有错误,欢迎指正

  • 相关阅读:
    十天冲刺个人博客四
    十天冲刺个人博客三
    十天冲刺个人博客二
    软件工程课堂七(单词统计)
    十天冲刺个人博客一
    软件工程第九周总结
    人月神话阅读笔记03
    软件工程课堂六(《飘》单词统计)
    软件工程第八周总结
    跨域
  • 原文地址:https://www.cnblogs.com/lfz1211/p/12704394.html
Copyright © 2020-2023  润新知