有趣的编程题

程序员猪佩琪 2009-07-23 09:04:09
给一个无限长的自然数构成的字符串
S:12345678910111213141516…,它是由所有
自然数从小到大依次排列起来的,任意给一个数
字串S1,编程求出它第一次出现的位置。


...全文
1115 94 打赏 收藏 转发到动态 举报
写回复
用AI写文章
94 条回复
切换为时间正序
请发表友善的回复…
发表回复
程序员猪佩琪 2009-08-11
  • 打赏
  • 举报
回复
[Quote=引用 77 楼 pioneer604 的回复:]
嗯,我计算索引的公式错了,汗,一开始还是对的,后来改成错的了

Java codepackage quiz;import java.io.*;publicclass Headache {private String analysis;privateint digits;privateint rstOffset, rstDiv;privatelong rstIndex= Long.MAX_VALUE;

Headache(String src) {
analysis= src;
digits= src.length();
}publicvoid analyse() {boolean find=false;if (Long.parseLong(analysis)==0) {
rstOffset=-1;
rstDiv= digits+1;
rstIndex= calIndex(-1, digits+1);
}for (int n=1; n<= digits; n++) {// 对同一个n的不同offset匹配结果须比较大小if (find) {return;
}
inner1:for (int offset=0; offset< n; offset++) {int i= n;// 当前最高位数int index=0;// 当前索引boolean carry=false;// 是否产生进位 String pre;
String suc;if (offset!=0) {
pre= analysis.substring(0, offset);
index+= offset;
}else {
pre= analysis.substring(0, i);
index+= i;
}if (hasLeadingZero(pre)&& offset==0) {continue inner1;
}if (isMax(pre)&& offset==0) {
i++;
carry=true;
}while (true) {if (index+ i>= digits) {if (offset==0&& n== digits) {if (!hasLeadingZero(analysis)) {
rstOffset= offset;
rstDiv= n;
rstIndex= calIndex(offset, n);
find=true;
}continue inner1;
}if (index== digits) {if (calIndex(offset, n)< rstIndex) {
rstOffset= offset;
rstDiv= n;
rstIndex= calIndex(offset, n);
find=true;
}continue inner1;
}
suc= analysis.substring(index, digits);if (hasLeadingZero(suc)) {continue inner1;
}if (carry) {if (suc.equals(suc.replaceAll("\\d","0")
.replaceFirst("\\d","1"))) {if (calIndex(offset, n)< rstIndex) {
rstOffset= offset;
rstDiv= n;
rstIndex= calIndex(offset, n);
find=true;
}
}
}else {if (offset!=0&& index== offset) {if (suc.length()- (digits- n)<0|| n== digits) {if (calIndex(offset, n)< rstIndex) {
rstOffset= offset;
rstDiv= n;
rstIndex= calIndex(offset, n);
find=true;
}
}elseif (String.format(
String.format("%%0%dd", n),
Long.parseLong(pre)+1).substring(
suc.length()- (digits- n),
suc.length()).equals(
suc.substring(suc.length()- (digits- n), suc.length()))) {if (calIndex(offset, n)< rstIndex) {
rstOffset= offset;
rstDiv= n;
rstIndex= calIndex(offset, n);
find=true;
}

}continue inner1;
}if (String.valueOf(Long.parseLong(pre)+1)
.substring(0, suc.length()).equals(suc)) {if (calIndex(offset, n)< rstIndex) {
rstOffset= offset;
rstDiv= n;
rstIndex= calIndex(offset, n);
find=true;
}
}
}continue inner1;
}

suc= analysis.substring(index, index+ i);if (hasLeadingZero(suc)) {continue inner1;
}if (carry) {if (!suc.equals(suc.replaceAll("\\d","0")
.replaceFirst("\\d","1"))) {continue inner1;
}else {
carry=false;
}
}else {if (offset!=0&& index== offset) {if (!String.format(String.format("%%0%dd", n),
Long.parseLong(pre)+1).substring(
n- offset, n).equals(
suc.substring(n- offset, n))) {continue inner1;
}
}else {if (!String.valueOf(Long.parseLong(pre)+1)
.equals(suc)) {continue inner1;
}
}
}
index+= i;if (isMax(suc)) {
i++;
carry=true;
}
pre= suc;
}
}
}
}publicboolean hasLeadingZero(String test) {return test.charAt(0)=='0';
}publicboolean isMax(String test) {return test.equals(test.replaceAll("\\d","9"));
}public String getFstNum(int argOffset,int argDiv) {if (argDiv== digits+1) {return"1"+ analysis;
}
String tmpOne;if (argOffset+ argDiv> digits) {int len= argDiv- (digits- argOffset);
String tmp= String.format(String.format("%%0%dd", len),
Long.parseLong(analysis.substring(argOffset- len,
argOffset))+1);
tmpOne= analysis.substring(argOffset, digits)+ tmp.substring(tmp.length()- len, tmp.length());
}else {
tmpOne= analysis.substring(argOffset, argOffset+ argDiv);
}return tmpOne;
}publiclong calIndex(int argOffset,int argDiv) {
String tmpTwo= getFstNum(argOffset, argDiv);long total=0;for (int i=1; i< tmpTwo.length(); i++) {
total+=9* i* Math.pow(10, i-1);
}
total+= tmpTwo.length()* (Long.parseLong(tmpTwo)- Math.pow(10, tmpTwo.length()-1));
total-= argOffset;return total;
}publicvoid Print() {
analyse();
System.out.println("the input String:"+ analysis);
System.out.println("the first extracted number is"+ getFstNum(rstOffset, rstDiv)+" rstOffset(在输入串中出现的位置):"+ rstOffset+" rstDiv(位数):"+ rstDiv);
System.out.println("the position of first appearance is"+ (rstIndex+1));
}publicstaticvoid main(String[] args)throws IOException {// 空行或 Ctrl - Z 结束程序 BufferedReader stdin=new BufferedReader(new InputStreamReader(
System.in));
String s;while ((s= stdin.readLine())!=null&& s.length()!=0) {
Headache tm=new Headache(s);
tm.Print();
}
}
}
[/Quote]
大家都来测测吧,看看有没有bug!
WuBill 2009-08-09
  • 打赏
  • 举报
回复
这个题目确实有意思
aaron532725130 2009-08-08
  • 打赏
  • 举报
回复
这题用的代码不用很长,
微软大饼(69楼)的代码不错,代码精炼,pioneer604大哥代码太长了,可以算出结果但是麻烦了。。。。
程序员猪佩琪 2009-08-08
  • 打赏
  • 举报
回复
[Quote=引用 83 楼 aaron532725130 的回复:]
这题用的代码不用很长,
微软大饼(69楼)的代码不错,代码精炼,pioneer604大哥代码太长了,可以算出结果但是麻烦了。。。。

[/Quote]
兄弟,不要看代码长短呀,要看效率哦,在给定的字符串不是太长的情况下,两个程序执行效率可能没有太大的区别,但是如果给定的字符串很长的情况下,效率一下就出来了!
pioneer604 2009-08-08
  • 打赏
  • 举报
回复
因为这题编得时间比较长,所以后来有点晕了,把计算索引的公式由对的改成错的了,思路大体上是这样,具体你可以看一下我63楼的帖子,后面的兄弟如果编得话尽量按照先构造模式串再看是否相等的方法做,这样能简洁一点,至于有人觉得比较容易的就能搞定这个程序,我觉得可能性不大

[Quote=引用 90 楼 humanity 的回复:]
我觉得还有点小问题:
1.要求任意长度,所以不能用 int / long 而要用 BigInteger.
2.我们可以首先分析要查找的数字本身是否多个数拼在一起,因为拼在一起的数是后一个比并一个+1,很容易知道是不是,首先推测它可能是几种情况,然后再试,因为 s1 比起 S 来说很短,分析更省时间,得到几个可能的情况后再查找。没注释看不懂程序啊,不知道是不是这么做的。

我测试了一下这个程序觉得好像是有错误的,下面这两个输入是否存在,它的结果位置应该只差3,实际上差了很21:
99100101
the input String: 99100101
the first extracted number is 99 rstOffset(在输入串中出现的位置): 0 rstDiv(位数):2
the position of first appearance is 188
00101102
the input String: 00101102
the first extracted number is 101 rstOffset(在输入串中出现的位置): 2 rstDiv(位数):3
the position of first appearance is 209

[/Quote]
humanity 2009-08-08
  • 打赏
  • 举报
回复
搞错了,我把你前面的代码贴了。新的代码是只差3.
humanity 2009-08-08
  • 打赏
  • 举报
回复
我觉得还有点小问题:
1.要求任意长度,所以不能用 int / long 而要用 BigInteger.
2.我们可以首先分析要查找的数字本身是否多个数拼在一起,因为拼在一起的数是后一个比并一个+1,很容易知道是不是,首先推测它可能是几种情况,然后再试,因为 s1 比起 S 来说很短,分析更省时间,得到几个可能的情况后再查找。没注释看不懂程序啊,不知道是不是这么做的。

我测试了一下这个程序觉得好像是有错误的,下面这两个输入是否存在,它的结果位置应该只差3,实际上差了很21:
99100101
the input String: 99100101
the first extracted number is 99 rstOffset(在输入串中出现的位置): 0 rstDiv(位数):2
the position of first appearance is 188
00101102
the input String: 00101102
the first extracted number is 101 rstOffset(在输入串中出现的位置): 2 rstDiv(位数):3
the position of first appearance is 209
yanguobin2004 2009-08-08
  • 打赏
  • 举报
回复
我是88楼,已经解决这个问题,快给分!
yanguobin2004 2009-08-08
  • 打赏
  • 举报
回复
//解析这个数是单独的还是由多个数组成的。如s="1516",是由15和16组成,出现在1516的前面,那么就应该算15的位置,而不是1516的位置
public static String getNumber(String s)
{
int len=s.length()/2;
for(int i=1;i<=len;i++)
{
String fs=s.substring(0,i);
long l=Long.parseLong(fs);

while(true)
{
l++;
fs=fs+String.valueOf(l);
if(fs.length()>=s.length())
{
break;
}
}
if(fs.equals(s))return s.substring(0,i);
}
return s;
}
//长度是1的数字有9个,那么长度是2的就是99-9=90,长度是3的就是999-99=900,那么长度为n就是9乘以10的n-1次方
public static long getPosition(String n)
{
long len=n.length();//数的长度
long l=Long.parseLong(n);
long c=0;
long l1=len*l;
for(int i=0;i<len;i++)
{
c+=9*(long)Math.pow(10,i)*(len-(i+1));
}
long l2=l1-c;
l2=l2-len;//里面包括了这个数的长度,所以要减去

return l2;

}

public static void main(String[] args)
{
System.out.print(getPosition(getNumber("1617")));
}
浅野忠信 2009-08-08
  • 打赏
  • 举报
回复
[Quote=引用 84 楼 liuwenjie517333813 的回复:]
[Quote=引用 84 楼 liuwenjie517333813 的回复:]


兄弟,不要看代码长短呀,要看效率哦,在给定的字符串不是太长的情况下,两个程序执行效率可能没有太大的区别,但是如果给定的字符串很长的情况下,效率一下就出来了!
[/Quote]效率[/Quote]
longq121 2009-08-08
  • 打赏
  • 举报
回复
算法问题,学习了
wlovecyy 2009-08-08
  • 打赏
  • 举报
回复
两位数是90个
zhuwen9 2009-08-07
  • 打赏
  • 举报
回复

package com.test;

public class FindNumber {

/**
* @param args
*/
public static void main(String[] args) {
// TODO Auto-generated method stub
int num=1253;
int length=(num+"").length();
int possition=0;
////规律
/*if (length==1) {
possition=num;
}
if (length==2) {
possition=10+(num-10)*2;
}
if (length==3) {
possition=(10-0)*1+(100-10)*2+(num-100)*3;
}
if (length==4) {
possition=(10-0)*1+(100-10)*2+(1000-100)*3+(num-1000)*4;
}
System.out.println(possition);
possition=0;*/
for (int i = 1; i <length; i++) {
possition+=(power(i)-power(i-1))*i;
}
System.out.println(possition);
possition=possition+(num-power(length-1))*length;
System.out.println(possition);

}
public static int power(int i){
if (i==0) {
return i;
}
int b=1;
for (int j = 0; j < i; j++) {
b=b*10;
}
return b;
}

}
pioneer604 2009-08-06
  • 打赏
  • 举报
回复
哥们,各位一起试试,这是我编过的BUG最多的小程序了,惭愧
[Quote=引用 76 楼 gqz1985 的回复:]
你先把 我贴的代码部署你那里
两个程序对比着测试就明显了
[/Quote]
pioneer604 2009-08-06
  • 打赏
  • 举报
回复
嗯,我计算索引的公式错了,汗,一开始还是对的,后来改成错的了


package quiz;

import java.io.*;

public class Headache {
private String analysis;
private int digits;
private int rstOffset, rstDiv;
private long rstIndex = Long.MAX_VALUE;

Headache(String src) {
analysis = src;
digits = src.length();
}

public void analyse() {
boolean find = false;
if (Long.parseLong(analysis) == 0) {
rstOffset = -1;
rstDiv = digits + 1;
rstIndex = calIndex(-1, digits + 1);
}
for (int n = 1; n <= digits; n++) {
// 对同一个n的不同offset匹配结果须比较大小
if (find) {
return;
}
inner1: for (int offset = 0; offset < n; offset++) {
int i = n; // 当前最高位数
int index = 0; // 当前索引
boolean carry = false; // 是否产生进位
String pre;
String suc;
if (offset != 0) {
pre = analysis.substring(0, offset);
index += offset;
} else {
pre = analysis.substring(0, i);
index += i;
}
if (hasLeadingZero(pre) && offset == 0) {
continue inner1;
}
if (isMax(pre) && offset == 0) {
i++;
carry = true;
}
while (true) {
if (index + i >= digits) {
if (offset == 0 && n == digits) {
if (!hasLeadingZero(analysis)) {
rstOffset = offset;
rstDiv = n;
rstIndex = calIndex(offset, n);
find = true;
}
continue inner1;
}
if (index == digits) {
if (calIndex(offset, n) < rstIndex) {
rstOffset = offset;
rstDiv = n;
rstIndex = calIndex(offset, n);
find = true;
}
continue inner1;
}
suc = analysis.substring(index, digits);
if (hasLeadingZero(suc)) {
continue inner1;
}
if (carry) {
if (suc.equals(suc.replaceAll("\\d", "0")
.replaceFirst("\\d", "1"))) {
if (calIndex(offset, n) < rstIndex) {
rstOffset = offset;
rstDiv = n;
rstIndex = calIndex(offset, n);
find = true;
}
}
} else {
if (offset != 0 && index == offset) {
if (suc.length() - (digits - n) < 0
|| n == digits) {
if (calIndex(offset, n) < rstIndex) {
rstOffset = offset;
rstDiv = n;
rstIndex = calIndex(offset, n);
find = true;
}
} else if (String.format(
String.format("%%0%dd", n),
Long.parseLong(pre) + 1).substring(
suc.length() - (digits - n),
suc.length()).equals(
suc.substring(suc.length()
- (digits - n), suc.length()))) {
if (calIndex(offset, n) < rstIndex) {
rstOffset = offset;
rstDiv = n;
rstIndex = calIndex(offset, n);
find = true;
}

}
continue inner1;
}
if (String.valueOf(Long.parseLong(pre) + 1)
.substring(0, suc.length()).equals(suc)) {
if (calIndex(offset, n) < rstIndex) {
rstOffset = offset;
rstDiv = n;
rstIndex = calIndex(offset, n);
find = true;
}
}
}
continue inner1;
}

suc = analysis.substring(index, index + i);
if (hasLeadingZero(suc)) {
continue inner1;
}
if (carry) {
if (!suc.equals(suc.replaceAll("\\d", "0")
.replaceFirst("\\d", "1"))) {
continue inner1;
} else {
carry = false;
}
} else {
if (offset != 0 && index == offset) {
if (!String.format(String.format("%%0%dd", n),
Long.parseLong(pre) + 1).substring(
n - offset, n).equals(
suc.substring(n - offset, n))) {
continue inner1;
}
} else {
if (!String.valueOf(Long.parseLong(pre) + 1)
.equals(suc)) {
continue inner1;
}
}
}
index += i;
if (isMax(suc)) {
i++;
carry = true;
}
pre = suc;
}
}
}
}

public boolean hasLeadingZero(String test) {
return test.charAt(0) == '0';
}

public boolean isMax(String test) {
return test.equals(test.replaceAll("\\d", "9"));
}

public String getFstNum(int argOffset, int argDiv) {
if (argDiv == digits + 1) {
return "1" + analysis;
}
String tmpOne;
if (argOffset + argDiv > digits) {
int len = argDiv - (digits - argOffset);
String tmp = String.format(String.format("%%0%dd", len),
Long.parseLong(analysis.substring(argOffset - len,
argOffset)) + 1);
tmpOne = analysis.substring(argOffset, digits)
+ tmp.substring(tmp.length() - len, tmp.length());
} else {
tmpOne = analysis.substring(argOffset, argOffset + argDiv);
}
return tmpOne;
}

public long calIndex(int argOffset, int argDiv) {
String tmpTwo = getFstNum(argOffset, argDiv);
long total = 0;
for (int i = 1; i < tmpTwo.length(); i++) {
total += 9 * i * Math.pow(10, i - 1);
}
total += tmpTwo.length()
* (Long.parseLong(tmpTwo) - Math.pow(10, tmpTwo.length() - 1));
total -= argOffset;
return total;
}

public void Print() {
analyse();
System.out.println("the input String: " + analysis);
System.out.println("the first extracted number is "
+ getFstNum(rstOffset, rstDiv) + " rstOffset(在输入串中出现的位置): "
+ rstOffset + " rstDiv(位数):" + rstDiv);
System.out.println("the position of first appearance is "
+ (rstIndex + 1));
}

public static void main(String[] args) throws IOException {
// 空行或 Ctrl - Z 结束程序
BufferedReader stdin = new BufferedReader(new InputStreamReader(
System.in));
String s;
while ((s = stdin.readLine()) != null && s.length() != 0) {
Headache tm = new Headache(s);
tm.Print();
}
}
}

gqz1985 2009-08-06
  • 打赏
  • 举报
回复
你先把 我贴的代码部署你那里
两个程序对比着测试就明显了
bigbug9002 2009-08-06
  • 打赏
  • 举报
回复
9 + 99 * 2 = 207:这个公式不对,应该是9+90*2=189
gqz1985 2009-08-06
  • 打赏
  • 举报
回复
难道我把String src = "12345678910..101"都构造出来了
再求src.length计算机能求错
src.length就是192
gqz1985 2009-08-06
  • 打赏
  • 举报
回复
你错了
一位数确实是9个,两位数是90个
9+90*2=189 189加上100的3个数是192
pioneer604 2009-08-06
  • 打赏
  • 举报
回复
兄弟,这个你可以手工算一下,一位数有9个,两位数有99个,9 + 99 * 2 = 207, 再加一就是208了

[Quote=引用 71 楼 gqz1985 的回复:]
我已经把你的程序贴到Eclipse里,并测试“100”第一次出现的位置结果:
“the position of first appearance is 208”

我用我写的测试结果:
“字符串长度192
the input String: 100
the position of first appearance is:189”

很明显“100”在“98 99 100 101”的时候首次出现,你的好像还不是很正确,因为src的长度才192
[/Quote]
加载更多回复(74)

62,620

社区成员

发帖
与我相关
我的任务
社区描述
Java 2 Standard Edition
社区管理员
  • Java SE
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

试试用AI创作助手写篇文章吧