腾讯有一道机试题: 
大概意思是: 
小Q非常富有,拥有非常多的硬币,小Q的拥有的硬币是有规律的,对于所有的非负整数K,小Q恰好> 各有两个数值为2^k,的硬币,所以小Q拥有的硬币是1,1,2,2,4,4……,小Q卖东西需要支付元钱,请问小Q想知道有多少种组合方案。 
输入:一个n (1<=n<=10^18),代表要付的钱 
输出:表示小Q可以拼凑的方案数目

输入样例:6
输出样例:3
即:4+2,4+1+1,2+2+1+1

暴力解法

容易得知,对于输入N,所需硬币最大值不会超过N,即只需从1~^logN这些硬币拼凑。每种硬币可选0~2个,共三种选法。排列组合共3^logN种。

回溯法:耗费略优于暴力解法

import java.util.Scanner;
public class Main {
private static int n; //支付数
private static int count=0;
private static int[] p=null; //p[i]记录2^i元的硬币用了多少个,取值0~2 //初始化数组大小
private static void init(){
double lo=Math.log(n)/Math.log(2);
int length=(int)lo+1;
p=new int[length];
} //取值并回溯
private static final void solve(int i){
if(i>=p.length) return;
for(int t=0;t<=2;t++){
p[i]=t;
if(isOK()) count++;
else if(isPart()) solve(i+1);
}
p[i]=0;
} //判断是否当前是否等于n
private static boolean isOK(){
int sum=0;
for(int i=0;i<p.length;i++){
sum+=Math.pow(2, i)*p[i];
}
if(sum==n) return true;
else return false;
} //是否进行延伸
private static boolean isPart(){
int sum=0;
for(int i=0;i<p.length;i++){
sum+=Math.pow(2, i)*p[i];
}
if(sum<n) return true;
else return false;
} public static void main(String[] args){
Scanner scanner=new Scanner(System.in);
n=scanner.nextInt();
scanner.close();
double start=System.currentTimeMillis();
init();
solve(0);
System.out.println(count);
System.out.println("use time="+(System.currentTimeMillis()-start));
}
}

动态规划:耗费远小于回溯

使用res[n,i]表示:使用1,1,2,2,4,4,...,2^i,2^i可以组合出n的方案数
可见

res[n,i]=1,当n=0,即所有面值的硬币所取数目都为0
res[n,i]=1,当n=1,即只取一个一元的硬币
res[2,0]=1,即只取两个一元硬币
res[n,0]=0,当n>=3,因为无法只使用1,1组成大于等于3的组合
res[n,i]=sum(res[n-2^i*m,i-1]) n,i取其他,0=<m<=2
import java.util.Scanner;
public class Main {
private static int n; //支付数
private static int count=0;
private static int[][]res=null; //初始化数组
private static void init(){
double lo=Math.log(n)/Math.log(2);
int length=(int)lo+1;
res=new int[n+1][length];
for(int i=0;i<res[0].length;i++){
res[0][i]=1;
res[1][i]=1;
} res[1][0]=1;
res[2][0]=1;
} //动态规划
private static final int solve(){
if(n==0) return 1;
if(n==1) return 1; init();
for(int i=1;i<n+1;i++){
for(int j=1;j<res[0].length;j++){
int sum=0;
for(int m=0;m<3;m++){
int rest=(int) (i-Math.pow(2, j)*m);
if(rest>=0)
{
sum+=res[rest][j-1];
}
}
res[i][j]=sum;
}
}
return res[n][res[0].length-1];
} public static void main(String[] args){
Scanner scanner=new Scanner(System.in);
n=scanner.nextInt();
scanner.close();
double start=System.currentTimeMillis();
int result=solve();
System.out.println(result);
System.out.println("use time="+(System.currentTimeMillis()-start));
}
}
结果分析:
回溯:测试通过,n=10000时,耗费15s
动态规划:测试通过,n=10000时,耗费32ms

第四种方法:一种很有趣的思路

将硬币分为两份:1,2,4,8,16,.....和1,2,4,8,16....
组成两个数值为a,b的两个数字,他们的和是a+b=n;
a在每一份中只可能有一种组合方式(二进制的思想)。
将a和b使用二进制表示,那么对于n=11,有a=101,b=110这种组合,即a=1+0+4=5,b=0+2+4=6。但是,请注意,对于a和b,在相同位取不同值,只有一种组合方法。
如111+100和101+110(即交换中间位)本质上都是同一种组合方法,因此对于该类型可以使用二进制异或进行去重。
import java.util.HashSet;
import java.util.Scanner;
import java.util.Set; public class Main {
public static void main(String[] args) {
Scanner scanner=new Scanner(System.in);
int n=scanner.nextInt();
if(n<=2) {
System.out.println(n);
return;
}
Set<Integer> countset=new HashSet<>();
int stop=n/2;
for(int i=1;i<=stop;i++) {
int result=(i)^(n-i);//异或a和b
countset.add(result);
}
System.out.println(countset.size());
}
}

腾讯笔试题:小Q硬币组合的更多相关文章

  1. 算法题14 小Q歌单,牛客网,腾讯笔试题

    算法题14 小Q歌单,牛客网,腾讯笔试题 题目: 小Q有X首长度为A的不同的歌和Y首长度为B的不同的歌,现在小Q想用这些歌组成一个总长度正好为K的歌单,每首歌最多只能在歌单中出现一次,在不考虑歌单内歌 ...

  2. 算法题16 贪吃的小Q 牛客网 腾讯笔试题

    算法题16 贪吃的小Q 牛客网 腾讯笔试题 题目: 链接:https://www.nowcoder.com/questionTerminal/d732267e73ce4918b61d9e3d0ddd9 ...

  3. mysql笔试题大餐---1、组合查询方式及having

    mysql笔试题大餐---1.组合查询方式及having 一.总结 一句话总结: 实践:我之前的mysql真的学的太浅了,这种情况下,依据实践(做题)才是唯一能把它学好的方式 学的暂时够了,以实践而学 ...

  4. 远光软件ASP.NET笔试题小汇总

    ASP.NET笔试题是ASP.NET程序员面试必须经历的,一般会叫你填两个表 1个是你的详细信息表 1个是面试题答卷 两个都要注意反正面是否都有内容不要遗漏,如果考你机试一般也有两种,就是程序连接数据 ...

  5. Linux fork函数具体图解-同一时候分析一道腾讯笔试题

    原创blog.转载请注明出处 头文件: #include<unistd.h> #include<sys/types.h> 函数原型: pid_t fork( void); (p ...

  6. 腾讯笔试题 构造回文(LCS问题)

    给定一个字符串s,你可以从中删除一些字符,使得剩下的串是一个回文串.如何删除才能使得回文串最长呢? 输出需要删除的字符个数. 输入描述: 输入数据有多组,每组包含一个字符串s,且保证:1<=s. ...

  7. java线程同步问题——由腾讯笔试题引发的风波

    刚刚wm问我了一道线程的问题,因为自己一直是coder界里的渣渣.所以就须要恶补一下. 2016年4月2号题目例如以下. import java.util.logging.Handler; /** * ...

  8. acwing 算法面试、笔试题公开课整理记录

    week1 Google KickStart 2019 A轮 讲解视频地址AcWing 549. 训练   tag: 排序 遍历 在线练习地址AcWing 550. 包裹       在线练习地址Ac ...

  9. 剑指Offer——腾讯+360+搜狗校招笔试题+知识点总结

    剑指Offer--腾讯+360+搜狗校招笔试题+知识点总结 9.11晚7:00,腾讯笔试.选择题与编程.设计题单独计时. 栈是不是顺序存储的线性结构啊? 首先弄明白两个概念:存储结构和逻辑结构. 数据 ...

随机推荐

  1. SLF4J - 借助SLF4J, 统一适配所有日志实现为logback日志实现的实践

    一.屏蔽各种日志实现,去掉各种日志实现的实现依赖 二.引入slf4j和各种日志实现的适配器 1.引入slf4j 2.引入各种日志实现的适配器(适配到slf4j) 3.引入logback 引入logba ...

  2. api-gateway实践(05)新网关工作 - 缓存定义

    一.缓存分类 1.服务注册信息 1.1.[GroupCode_VersionCode]对应[Version定义]的缓存                       缓存类型:hash         ...

  3. 京东2019春招Java工程师编程题题解

    生成回文串 题目描述 对于一个字符串,从前开始读和从后开始读是一样的,我们就称这个字符串是回文串. 例如"ABCBA","AA","A"是回 ...

  4. C# 文件操作类大全

      C# 文件操作类大全 时间:2015-01-31 16:04:20      阅读:1724      评论:0      收藏:0      [点我收藏+] 标签: 1.创建文件夹 //usin ...

  5. Win10系统Python虚拟环境安装

    1.安装virtualenv 若要使用python虚拟环境进行开发,首先需要安装virtualenv. 命令:pip install virtualenv 2.安装虚拟环境 命令:virtualenv ...

  6. hdu1009 FatMouse' Trade---贪心

    题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=1009 题意:一共有n个房子,每个房子里有老鼠喜欢吃的javabeans,但是每个房间里的javabea ...

  7. 微信小程序:wx.request之post请求后端无法获取数据的问题

    前言:小程序的开发中总是踩到各种坑,看文档也不知所云: 例如当我们在写微信小程序接口时,method请求方式有POST和GET两种,为了数据安全,我们会偏向于使用POST请求方式访问服务器端: 问题: ...

  8. markdown常用语法简记

    一级标题 二级标题 三级标题 ..... 无序列表 First Second Third 有序列表 第一条 第二条 第三条 链接 我的github主页 锚点 无序列表 代码块 var vm = new ...

  9. 关于oracle11g在window10环境下安装不满足最低要求问题:报错NS-13001

    安装oracle11g时遇到INS-13001环境不满足最低要求: oracle在安装前会自动检测电脑配置,主要是内存的满足,但是博主最近在window10上装oracle11g时,发生了不满足最低要 ...

  10. 如何降低移动APP的开发成本

    在当下竞争激烈的商业世界中,移动APP开发是您业务的有利补充.移动APP可通过吸引新客户和保留现有客户,帮助公司成功开展业务.定制一个属于自己公司的移动APP扮演着重要角色,手机APP可以说通过轻松处 ...