针对规模有限的算法题技巧----打表

引入

比如我们要求某数组中的每个数字的质数因子,比如 9 = 3 ∗ 3 9=3*3 9=33,但数组中给的数是范围是1-1000

我们可以设置一个求出1-1000的质数的表(放在静态区),每个用例直接用这个表就行。

打表找规律

例题1:

小虎买苹果,他有装8个苹果的袋子和装6个苹果的袋子,要求袋子最少,且用的袋子都满了。

暴力法先把结果打出来,尽可能用8号袋装,然后看剩余结果能否用6号袋装,不行,就把8号袋减去一个,再看能不能用6号袋装…把每个值打印出来,找规律。

public class abc {
    static int mink;


    //tested
    public static boolean issix(int num)
    {
        if(num%6==0)
            return true;
        else
            return false;
    }


    public static int buyapples(int apples)
    {
        if(apples==0)
            return -1;
        System.out.print(apples+":");
      int n=apples/8;
      while(n!=-1&&!issix(apples-n*8))
      {
          n-=1;
      }
      if(n==-1)
          return -1;
      return n+(apples-n*8)/6;

    }

    //把1-100的苹果打印出来
    public static void main(String[] args) {
        for(int i=0;i<100;i++)
        {
            System.out.print(buyapples(i));
            System.out.println();
        }
    }
}
找规律!!

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-uuZwbiIv-1610760882019)(E1EE042FF86F48568660B49CC2B1F3F0)]

  1. 0返回-1
  2. 奇数返回-1
  3. 会发现从3以后,每个数字都对应4个apples的数量,且最后一个对应的apples数量就是8*i
    [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-wijdDVfR-1610760882022)(B34D31C97E2D4826A9F0412FAC77A8C7)]
O(1)完美解决该题,程序中试了全都一样。数学原理是满8的递减2(不太重要),
 public static int buyapples2(int apples)
    {

        if(apples==6||apples==8)
            return 1;

        if(apples==12|apples==14||apples==16)
            return 2;
        if(apples<=13)
            return -1;
       if(apples==0||apples%2==1)
           return -1;
       if(apples%8==0)
           return apples/8;
       else
           return apples/8+1;
    }
例题2:

给定一个正整数N,表示有N份青草统一堆放在仓库里
有一只牛和一只羊,牛先吃,羊后吃,它俩轮流吃草
不管是牛还是羊,每一轮能吃的草量必须是:
1,4,16,64…(4的某次方)
谁最先把草吃完,谁获胜
假设牛和羊都绝顶聪明,都想赢,都会做出理性的决定
根据唯一的参数N,返回谁会赢

eg分析:
草为1的时候,先手选1,先手赢
草为2的时候,先手选1,后手选1,后手赢
草为3的时候,先手选1,后手选1,先手选1,先手赢
草为4的时候,先手选4,先手赢
草为5的时候,先手选4,后手选1,后手赢;或者先手选1,后手选4,后手赢。
草为6的时候,先手选1,后手选4,先手选1,先手赢;或者先手选4,后手选1,先手赢。
看到这里,基本可以确定,草的数目后确定后,对应唯一的结果,这也是“绝顶聪明”的意思,因此我们可以着手写暴力法。

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-J2m5BU76-1610760882027)(CD969934AF9E420A8101FE188A176256)]

从6开始 会发现 “先后先先后” 的规律 改写成O(1)

public static String whowin2(int grass)
        {
            if(grass<5)
            {
                if(grass%2==0)
                    return"后手";
                if(grass%2==1)
                    return"先手";
            }
            int n=grass%5;
            if(n==1||n==3||n==4)
                return "先手";
            else
                return "后手";
            
        }
例题3:

定义一种数:可以表示成若干(数量>1)连续正数和的数
比如:
5 = 2+3,5就是这样的数
12 = 3+4+5,12就是这样的数
1不是这样的数,因为要求数量大于1个、连续正数和
2 = 1 + 1,2也不是,因为等号右边不是连续正数
给定一个参数N,返回是不是可以表示成若干连续正数和的数。

先手暴力解:

 public static boolean isthenum(int num)
        {
            for(int i=1;i<num;i++)
            {
                int sum=i;
                int j=i+1;
                while(true)
                {
                    sum+=j;
                    if(sum==num)
                        return true;
                    else if(sum>num)
                        break;
                    j+=1;
                }
            }
            return false;
        }

        public static void main(String[] args) {
            for(int i=1;i<=100;i++)
            {
                System.out.print(i+": ");
                System.out.print(isthenum(i)+"  ");
                if(i%10==0)
                    System.out.println();
            }
        }

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-feA8eBow-1610760882031)(E559AF8FA40D464FB0F59425FE9A8AA9)]

会发现:false很少:有1 ,2,4,8,16,32,64…2^n


        //tested
        //检测n是否是2的次方
        public static boolean islog2ed(int n)
        {
            double l=n;
            double q=Math.log(l)/Math.log(2);
            if(q==(int)q)
            {
                return true;
            }
            return false;

        }
        public static boolean isthenum2(int num)
        {
            if(islog2ed(num))
                return true;
            return false;
        }
  • 1
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值