Stack(篇1)计算全排列大于等于其的自然数

47 篇文章 37 订阅
6 篇文章 0 订阅

有一些自然数,其所有排列大于或等于该数字,例如。123,其所有置换(123,231,321)都大于或等于123。
给定自然数n,任务是计数从1到n的所有这样的数。
例子:

输入:N = 15 
输出:14 
1,2,3,4,5,6,7,8,9,11,12,
13,14,15是其所有的数字
排列比数大于
本身。因此,输出14. 
输入:n = 100. 
输出:54

解法1(暴力解法)
从1到n计算出每个数的全排列,然后比较全排列都大于或等于本身时,count++;


代码


public class Permutation {
    static int sum=0;
    public static void main(String[] args) {
        // TODO Auto-generated method stub
        int n=100;
        System.out.println(countNumber(n));
        for(int i=1;i<=n;i++)
        {
           sum+=permutation(i);
           //计算所有1到n符合条件的个数
        }
        System.out.println(sum);
    }
public static int permutation(int n)
    {
        int k=0;
        Stack<Integer> stack = new Stack<Integer>();
        permutation(array(n),k,0,stack);
        //找出n的全排列并将其放到stack中
        int count=Count(stack,n);
        //比较n和其全排列当全排列大于或等于n时count=1;   
        return count;
    }
    public static int Count(Stack< Integer> stack,int n)
    {
        while(!stack.isEmpty())
        {
            if(stack.pop()<n)
                return 0;           
        }
        return 1;       
    }
    public static int[] array(int n)
    {
    //将n按位分割放到数组中,好做全排序
        ArrayList<Integer> list=new ArrayList<Integer>();
        while(n!=0)
        {
            list.add(n%10);
            n=n/10;
        }
        int a[]=new int[list.size()];
        for(int i=0;i<list.size();i++)
            a[i]=list.get(i);
        return a;
    }
    public static void permutation(int a[],int k,int sum,Stack<Integer> stack)
    {
    //计算a[]的全排序
        if(k==a.length)
        {
//          System.out.println(sum);
            stack.push(sum);
        }
        else {

            for(int i=k;i<a.length;i++)
            {
                int temp;
                temp=a[i];
                a[i]=a[k];
                a[k]=temp;
                sum+=a[k]*Math.pow(10,a.length-k-1);
                permutation(a,k+1,sum,stack);
                sum-=a[k]*Math.pow(10,a.length-k-1);
                temp=a[i];
                a[i]=a[k];
                a[k]=temp;
            }
        }

    }

解法2(效率高代码精简)

解法2基于两点:
1: 自然数1–9都是满足全排序大于或等于本身的
2:满足全排序大于或等于本身的数n中的从高位到最低位一定是一个递增的序列,例如123的全排序为{123,132,213,231,312,321}都比自身大,而123中的数是递增的。
基于以上两点:可以用一个栈将之前算出来的全排序保存,后面的全排序一定是在之前的全排序上增加数,且该数大于或等于前面全排序的最后一个数:
比如说:12是全排序,那么在12的基础上123,124,125,126,127,128,129都是全排序,因此我们可以将12放到栈中然后1-9循环比较2与他们的大小如果大于2,则该数是满足条件将该数放到栈中。


代码


    public static int CountNum(int n)
    {
        int result=0;
        Stack< Integer> stack=new Stack<Integer>();
        for(int i=1;i<=9;i++)
        {
            if(i<=n)
            {
                //将1-9中小于n的值放到栈中因为1-9都符合条件
                stack.push(i);
                result++;
            }
        }
        while(!stack.isEmpty())
        {
            int top=stack.pop();
            //在基于条件的基础上例如1后面加上大于1的数也符合条件放到栈中
            for(int j=top%10;j<=9;j++)
            {
                int cur=top*10+j;
                if(cur<=n)
                {
                    stack.push(cur);
                    result++;
                }
            }
        }
            return result;
    }
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值