我将在几周内参加一个编程竞赛,并一直在处理过去的论文。我坚持的一个问题是调用一个递归函数,它计算所有可能的n位数的二进制整数,例如用户输入2,程序打印出00,01,10,11。解决这个问题的最佳方法是什么?怎么做?
此外,这是一场ACM比赛 - 是否有必要为这些比赛学习书籍?我应该读什么?这是一个月之内!我真的很紧张,不想让我的团队失望。
答案 0 :(得分:6)
Java中的解决方案:
for(int i = 0; i < 1 << n; i++)
{
System.out.println(Integer.toBinaryString(i));
}
答案 1 :(得分:3)
这里有一些没有实际限制的代码(你可以删除递归,但似乎这是答案的要求):
public class Bits {
public static void f(String prefix, int n) {
if (n == 0) {
System.out.println(prefix);
return;
}
f(prefix + "0", n - 1);
f(prefix + "1", n - 1);
}
public static void main(String [] argv) {
f("", 5);
}
}
答案 2 :(得分:2)
在C或C ++中可能是类似的东西,在这种情况下递归性并不是真正必要或更简单,但如果被问到......算法正是我要做的手工解决这个问题。从右到左改变1到0并传播进位,直到找到0.这在基数2中计算。作为一个练习你可以尝试在3或4基数,它没有太大的不同。
#include <stdio.h>
#include <malloc.h>
void f(char *buffer, int max){
int i;
printf("%s, ", buffer);
for (i = max-1 ; buffer[i] == '1' ; i--){
buffer[i] = '0';
}
if (i < 0) return;
buffer[i] = '1';
f(buffer, max);
}
int main(int argc, char ** argv){
int max = atoi(argv[1]);
char buffer[32];
int i;
for (i = 0; i < max ; i++){
buffer[i] = '0';
}
buffer[max] = 0;
f(buffer, max);
}
为了准备比赛,回顾过去的论文是一个好主意。但基本上你应该尽可能多地编写代码。您还应该训练以实现经典算法(树,排序,图形实现以及搜索最佳路径,列表,8个皇后等),同时您可以寻求帮助。一个月的时间并不是很长,所以你应该专注于理解一些经典问题。
我还建议习惯于单元测试,这样可以避免提出错误的答案,在这种竞争和单元测试中会受到惩罚,TDD无论如何都有助于关注问题,避免浪费你的时间。
答案 3 :(得分:1)
这不是java,但它是递归的。
function getBinaryDigitForPosition(currentLevel, currentNumberAsString) {
// if this were anything but binary I'd put these into an array and iterate thru
firstNumber = currentNumberAsString + "0";
secondNumber = currentNumberAsString + "1";
if (currentLevel == 1) {
print firstNumber + ", " + secondNumber;
} else {
// same iteration here as I mentioned above
getBinaryDigitForPosition(currentLevel - 1, firstNumber);
getBinaryDigitForPosition(currentLevel - 1, secondNumber);
}
}
// calling the function initially:
// make sure that userInputNumberOfDigits is >= 1
getBinaryDigitForPosition(userInputNumberOfDigits, "");
答案 4 :(得分:0)
编辑我写错了这个问题 - 这是用k位打印出长度为N的所有字符串。留下这个作为竞赛的建议。
有一个比O(2^n)
更好的解决方案,这里有一个提示 - 考虑长度为N的位串数与k个位的递归关系。设S是一个计算这些项数的函数
S(N,k) = S(N-1,k-1) + S(N-1,k)
用语言来说,重复归结为此 - 你可以添加一点或不添加一点。您可以使用memoization使此计算快速运行。你需要自己重现弦乐,但我把它留作练习。
通过阅读书籍可以学到很多东西(算法和算法设计手册介绍很好),以获得“全局”算法。剩下的就是有经验来找到那些算法何时适合这些问题,何时不适合以及如何在这种情况下编写特殊解决方案。我已经完成了其中的一些,但不能说我擅长他们,玩得开心,祝你好运:)
答案 5 :(得分:0)
这是一个java递归解决方案:)
public class BinaryIntegers {
public static void main(String[] args) {
int numberOfBits = 10; // For instance.
printBinaryNumbers(numberOfBits);
}
private static void printBinaryNumbers(int numberOfBits) {
recursivePrint("", numberOfBits);
}
private static void recursivePrint(String current, int numberOfBitsLeft){
if(numberOfBitsLeft==0)
System.out.println(current);
else{
recursivePrint(current + "0", numberOfBitsLeft-1);
recursivePrint(current + "1", numberOfBitsLeft-1);
}
}
}
答案 6 :(得分:0)
这是一个更通用的解决方案,它不仅可以创建二进制数字列表,还可以创建任何数字列表: - )
package de.fencing_game.paul.examples;
import java.util.Arrays;
public class AllNaryNumbers {
private static void printAll(String prefix, Iterable<String> digits,
int length)
{
if(length == 0) {
System.out.println(prefix);
return;
}
for(String digit : digits) {
printAll(prefix + digit, digits, length-1);
}
}
private static void printNumbers(int length, Iterable<String> digits) {
printAll("", digits, length);
}
private static void printBinary(int length) {
printNumbers(length, Arrays.asList("0", "1"));
}
public static void main(String[] params) {
if(params.length == 0) {
printBinary(5);
return;
}
int len = Integer.parseInt(params[0]);
if(params.length == 1) {
printBinary(len);
return;
}
Iterable<String> digits =
Arrays.asList(params).subList(1, params.length);
printNumbers(len, digits);
}
}
编辑:使用我的ProductIterable
时,代码会变短:
private static void printNumbers(int length, Iterable<String> digits)
{
for(List<String> number :
new ProductIterable<String>
(Collections.nCopies(length, digits))) {
for(String digit : number) {
System.out.print(digit);
}
System.out.println();
}
}
(大部分是将Iterable转换为字符串)。如果我们可以使用以逗号分隔的输出,我们可以使用ProductList
并使其更短:
private static void printNumbers(int length, List<String> digits)
{
System.out.println(new ProductList<String>
(Collections.nCopies(length, digits)));
}
输出将是这样的:[[0, 0, 0], [0, 0, 1], [0, 1, 0], [0, 1, 1], [1, 0, 0], [1, 0, 1], [1, 1, 0], [1, 1, 1]]
。
它不是递归的,但至少是懒惰的(及时)产生元素。
答案 7 :(得分:0)
有一本书:
http://www.amazon.com/exec/obidos/ISBN=0387001638/theinternationscA/
我的一个朋友收到了这样一本书(作为初级编程竞赛的价格),并且非常热衷于此,但我不确定它是否是这个(虽然它确实在亚马逊上有很好的评价)
准备的最佳方法是解决旧的编程问题。检查过去的问题集,总会出现一些问题:迷宫中的东西,动态编程的东西等。练习这些类型的问题,这样你就可以在真正的竞争中快速解决它们。
另外,不要低估参与编程竞赛的计划/组织的数量。团队成员之间的良好互动(例如,挑选哪些练习要解决)非常重要。也是如何修复错误程序的好方法。
另一件事,你说你真的很紧张,害怕让你的团队失望。但请记住,你是一个团队。一起练习!! 如果你要三个人去那里,你肯定会失去......(最好的方法就是失败:让一个团队成员声称某个问题,他不会解决,但是其中他确信自己“几乎就在那里”;从而占用了大量的计算机时间,并且没有任何解决方案......)
另外,想想你将如何工作。我个人最喜欢的是两个编码器和一个非编码器。这样,总有一个人使用计算机,而另一个编码器可以讨论非编码器的问题。 (通过编码器,我的意思是实际键入代码的人,而不仅仅是在纸上编写算法)
祝你好运!更重要的是:玩得开心!