一道笔试题

zengkun100 2007-01-14 01:57:44
加精
Trilogy公司的笔试题

如果n为偶数,则将它除以2,
如果n为奇数,则将它加1或者减1。
问对于一个给定的n,怎样才能用最少的步骤将它变到1。
例如:
n= 61
n-- 60
n/2 30
n/2 15
n++ 16
n/2 8
n/2 4
n/2 2
n/2 1


我的想法是这样的:
当n为偶数时,没得选择,除以2就好。所以关键是看对奇数时怎么处理。
当n为奇数时,如果为1,就结束了,如果不为1,那肯定可以表示成下面得等式:
n=m*2+1
此时选择对n是加1还是减1呢?
如果上式中的m是偶数的话,那n减1,因为m可以继续除以2。如果m是奇数的话,n加1,再除以2之后得到m+1,m+1是偶数可以继续除以2。当然n为3的时候应该减去1。

我觉得基本上就是“贪心”的思想。
...全文
7022 124 打赏 收藏 转发到动态 举报
AI 作业
写回复
用AI写文章
124 条回复
切换为时间正序
请发表友善的回复…
发表回复
bupt_xiaoz 2010-08-30
  • 打赏
  • 举报
回复
广搜吗不是,在加上剪枝
hanyuwei0 2010-05-19
  • 打赏
  • 举报
回复
我觉得111楼说的有道理
wasaa 2009-03-03
  • 打赏
  • 举报
回复
这个属于大学级别的数学吗
shunzi__1984 2009-02-12
  • 打赏
  • 举报
回复
收藏
Boyliang1987 2008-07-04
  • 打赏
  • 举报
回复
大家觉得我的程序如何?
#include<iostream.h>
void main()
{
int change(int b);
int a,time=0;
cout<<"请输入一个数:";
cin>>a;
cout<<a<<"->";
while((a=change(a))!=1)
{
cout<<a<<"->";
time++;
}
cout<<"最快经过"<<time<<"次可以变成1.";
}

int change(int a)
{
if(a==1)
return 1;
else if(a%2==0)
return a/2;
else if(((a-1)/2)%2==0)
return a-1;
else
return a+1;
}
adfas 2008-06-28
  • 打赏
  • 举报
回复
mark
poson 2008-06-17
  • 打赏
  • 举报
回复
继续看看二进制的方法
看一个数字靠近2的几次方。
在奇数的情况下
如15:1111;次高位是1,那么+1
如:1011,次高位是0,那么-1.
tianjiao85 2008-03-21
  • 打赏
  • 举报
回复
mark
missvip 2007-08-15
  • 打赏
  • 举报
回复
#include <iostream>
using namespace std;

void guiyi(unsigned int n)
{
cout<<n<<" ";
if(n==1)
{
cout<<endl;
return ;//递归结束
}
else
{
if(n%2==0)
{
guiyi(n/2);//如果是偶尔数,除以2继续递归
}
else
{
int temp=n-1;
if(temp%4==0)
{
n--;
cout<<n<<" ";
}
else
{
n++;
cout<<n<<" ";
}
guiyi(n/2);//如果是奇数,减去1除以2再递归
}
}
return ;
}

void main()
{
int NUM;
while(1)
{
cout<<"输入数据:";
cin>>NUM;
guiyi(NUM);
}

}
eumcsdn 2007-07-25
  • 打赏
  • 举报
回复
好帖子
pinejeely 2007-05-01
  • 打赏
  • 举报
回复
#include <iostream.h>

void RouteDisp(int n);
void EvenDisp(int n);
void OddDisp(int n);
void main()
{
int n;
cout<<"输入想归一的数:"<<endl;
cin>>n;
cout<<endl;
cout<<"最短路径为:"<<endl;
RouteDisp(n);
cout<<"Program is over!"<<endl;
}

void RouteDisp(int n)
{
if(n%2==0)
{
EvenDisp(n);
int tag=n/2;
RouteDisp(tag);
}
else
{
OddDisp(n);
int tag=(n-1)/2;
if(tag%2==0)
RouteDisp(tag-1);
else
RouteDisp(tag+1);
}
}

void EvenDisp(int n)
{
cout<<n<<"->";
}

void OddDisp(int n)
{
cout<<n<<"->";
}
不知道那错了。。。郁闷。。。
weicai_chen 2007-04-29
  • 打赏
  • 举报
回复
public class Trilogy {

public static void transferToOne (int n){
int temp = n;
int count = 0;

while(temp != 1){
if(temp % 2 == 0)
temp = temp / 2;
else if (temp == 3)
temp --;
else if(((temp - 1)/2) % 2 == 0)
temp--;
else
temp ++;

count ++;
}
System.out.println(n + " ---> " +count);
}

public static void main(String[] args){

for(int i = 1 ; i <= 100 ; i++)
transferToOne(i);
}
}


1 ---> 0
2 ---> 1
3 ---> 2
4 ---> 2
5 ---> 3
6 ---> 3
7 ---> 4
8 ---> 3
9 ---> 4
10 ---> 4
11 ---> 5
12 ---> 4
13 ---> 5
14 ---> 5
15 ---> 5
16 ---> 4
17 ---> 5
18 ---> 5
19 ---> 6
20 ---> 5
21 ---> 6
22 ---> 6
23 ---> 6
24 ---> 5
25 ---> 6
26 ---> 6
27 ---> 7
28 ---> 6
29 ---> 7
30 ---> 6
31 ---> 6
32 ---> 5
33 ---> 6
34 ---> 6
35 ---> 7
36 ---> 6
37 ---> 7
38 ---> 7
39 ---> 7
40 ---> 6
41 ---> 7
42 ---> 7
43 ---> 8
44 ---> 7
45 ---> 8
46 ---> 7
47 ---> 7
48 ---> 6
49 ---> 7
50 ---> 7
51 ---> 8
52 ---> 7
53 ---> 8
54 ---> 8
55 ---> 8
56 ---> 7
57 ---> 8
58 ---> 8
59 ---> 8
60 ---> 7
61 ---> 8
62 ---> 7
63 ---> 7
64 ---> 6
65 ---> 7
66 ---> 7
67 ---> 8
68 ---> 7
69 ---> 8
70 ---> 8
71 ---> 8
72 ---> 7
73 ---> 8
74 ---> 8
75 ---> 9
76 ---> 8
77 ---> 9
78 ---> 8
79 ---> 8
80 ---> 7
81 ---> 8
82 ---> 8
83 ---> 9
84 ---> 8
85 ---> 9
86 ---> 9
87 ---> 9
88 ---> 8
89 ---> 9
90 ---> 9
91 ---> 9
92 ---> 8
93 ---> 9
94 ---> 8
95 ---> 8
96 ---> 7
97 ---> 8
98 ---> 8
99 ---> 9
100 ---> 8
avril1986swj 2007-04-29
  • 打赏
  • 举报
回复
STUDY~~~~
UP~~~~~
luojxun 2007-04-29
  • 打赏
  • 举报
回复
我想到的最快方法,不用贪心的算法.因为除2是最快的,所以你在奇数时判断是加1更接近2的n次方还是减1更接近.
fixphy1985 2007-04-28
  • 打赏
  • 举报
回复
如果最后一个0之后是2个或者以下的连续1就减1,如果是三个或以上连续1就加1
star119119 2007-04-28
  • 打赏
  • 举报
回复
#include <iostream>
using namespace std;
int count=0;
int Func(int n){
count++;
if(n == 1) {
return n;
}else{
n=(n%2?n+1:n/2);
return Func( n);
}
}

void main(){
cout << Func(61) << endl; // 递归调用
cout << count << endl; // 运算次数
}

fdp0525 2007-04-28
  • 打赏
  • 举报
回复
学到不少东西啊 看来真的是来对了地方啊 这么多高手阿
Fortress 2007-04-26
  • 打赏
  • 举报
回复
这个原则挺好的:奇数除4余1是减1;除4余3时,继续观察除8余3则减1,不余3则加1;
没发现反例。
hilanderst 2007-04-23
  • 打赏
  • 举报
回复
我的想法:
1.向2^N靠:
例子:数13,2^3 < 13 < 2^4
D1= 16-13 =3 = 11(B)
D2= 13-8 =5 = 101(B)

2.计算D1,D2包含的1的个数:D1有2位,D2有两位;这是步骤中+1/-1的步骤

3.要考虑采用+1后,除以2的次数要增加1;
16->8->4->2->1,要4步;
8->4->2->1,要3步;
就是说,采用+1,要增加一步

综合以上1,2,3,对于13:
用减法的步骤:
2 //(减一的步骤)
+ 3 //(右移的步骤)
----------------------
5
用加法的步骤:
2 //(加一的步骤)
+ 4 //(右移的步骤)
----------------------
6
所以要采用减法。

这种方法应该很好证明,时间复杂度为O(lgN),空间复杂度为O(1).
abc130314 2007-04-20
  • 打赏
  • 举报
回复
近四原则是正确的,不过当这个数字=3时,除外

public class sx01 {
public static void main(String[] arge) {
int n=114708141;
int a=0;
System.out.print(n);
while ( n>1 ) {
if ( n%2==0 ) {
n=n/2;
a=a+1;
System.out.print(">>(/2)>>"+n);
}
else if ( n%4==1) {
n=n-1;
a=a+1;
System.out.print(">>(-1)>>"+n);
}
else if ( n==3 ) {
n=n-1;
a=a+1;
System.out.print(">>(-1)>>"+n);
}
else if ( n%4==3 ) {
n=n+1;
a=a+1;
System.out.print(">>(+1)>>"+n);
}
}
System.out.print("\n"+a);
}
}

可是这么理解, 当 把 X 用近四原则 约到 n时:
当n=1 时(二进制码 00000001 ),( +1 )之后再用近四原则会少用 -2 步;
当n=3 时(二进制码 00000011 ),( +1 )之后再用近四原则会少用 -1 步;
当n=7 时(二进制码 00000111 ),( +1 )之后再用近四原则会少用 0 步;
当n=15时(二进制码 00001111 ),( +1 )之后再用近四原则会少用 1 步;
当n=31时(二进制码 00011111 ),( +1 )之后再用近四原则会少用 2 步;
……
依次类推;

加载更多回复(104)

33,027

社区成员

发帖
与我相关
我的任务
社区描述
数据结构与算法相关内容讨论专区
社区管理员
  • 数据结构与算法社区
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

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