奇虎360_2017校园招聘笔试编程题第二题

今晚做了360的校招笔试题,编程题难度适中,在这里跟大家分享一下编程题的第二题。第二道题也不难想到思路,但是如果写法不当,可能无法满足题目的时间限制。

1、 题目
这里写图片描述

2、 输入输出及样例
这里写图片描述

3、 我的思路
最容易想到的思路就是从1到n判断每个数中的数组是否包含除0和1以后的字符。如果是,不计数,否则总数量加1。

4、 我的实现

import java.util.Scanner;

public class Ti2
{   
    public static void main(String[] args)
    {
        Scanner scanner = new Scanner(System.in);

        while(scanner.hasNextInt())
        {
            int n = scanner.nextInt();

            int count = 1;
            for(int i =2; i<=n; i++)
            {
                char[] get = String.valueOf(i).toCharArray();

                int flag = 0;
                for(int j=0; j<get.length; j++)
                {
                    if(get[j] != '0' && get[j] != '1')
                    {
                        flag  = 1;
                        break;
                    }                   
                }               
                if(flag == 0)
                {
                    count++;
                }           
            }
            System.out.println(count);
        }
    }
}

5、 第一次改进思路
但是以上实现通过率之后33.3%,提示是超时。经过简单的分析发现,可以通过输入n的位数来简化统计。当n的位数为k时,满足题设要求的数总量为(2的(k-1)次方)-1,再加上从10的k次方到n之间满足题设要求的数的总量。

6、 第一次改进后的实现

import java.util.Scanner;

public class Ti21
{   
    public static void main(String[] args)
    {
        Scanner scanner = new Scanner(System.in);

        while(scanner.hasNextInt())
        {
            int n = scanner.nextInt();

            int weishu = String.valueOf(n).length();

            int count = (int) (Math.pow(2, weishu-1)-1);

            for(int i = (int)Math.pow(10, weishu-1); i<=n; i++)
            {
                char[] get = String.valueOf(i).toCharArray();

                int flag = 0;
                for(int j=0; j<get.length; j++)
                {
                    if(get[j] != '0' && get[j] != '1')
                    {
                        flag  = 1;
                        break;
                    }                   
                }               
                if(flag == 0)
                {
                    count++;
                }           
            }
            System.out.println(count);
        }
    }
}

7、 第二次改进思路
经过改进后,通过率提升到了50%,提示仍然是超时。经过再次分析,发现上次改进中还是有些遗漏的地方。
输入的数为n,假定n的位数为k,k个1组成的数字为m。那么当n>=m时,满足题设要求的数的总量为(2的k次方)-1。当n小于m时,仍按照5中所述思路求解。

8、 第二次改进后的实现

import java.util.Scanner;

public class Ti22
{
    public static void main(String[] args)
    {   
        Scanner scanner = new Scanner(System.in);

        while(scanner.hasNextInt())
        {
            int n = scanner.nextInt();          
            int weishu = String.valueOf(n).length();            
            int count = 0;

            if(n >= generate(weishu))
            {
                count = (int) (Math.pow(2, weishu)-1);
            }
            else
            {
                count = (int) (Math.pow(2, weishu-1)-1);

                for(int i = (int)Math.pow(10, weishu-1); i<=n; i++)
                {
                    char[] get = String.valueOf(i).toCharArray();

                    int flag = 0;
                    for(int j=0; j<get.length; j++)
                    {
                        if(get[j] != '0' && get[j] != '1')
                        {
                            flag  = 1;
                            break;
                        }                   
                    }               
                    if(flag == 0)
                    {
                        count++;
                    }           
                }
            }           
            System.out.println(count);
        }
    }

    //生成n个1组成的n位数
    public static int generate(int n)
    {
        StringBuilder sb = new StringBuilder();
        for(int i=0; i<n; i++)
        {
            sb.append("1");
        }
        return Integer.parseInt(sb.toString());         
    }
}

9、 总结
经过两次改进后终于100%通过测试。这个题目想到思路并不难,但是如果没有思考仔细就可能超出题目的时间限制。当然,如果哪位大神有更好的解法,还望不吝赐教,不胜感激。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值