问对于一个给定的n,怎样才能用最少的步骤将它变到1

如果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

算法设计:首先想到的是递规算法,不过细想一下我们可以动态规划:设a(i)为整数i用最少步骤变成1的解,设n=i+1 那么我们考虑a(n),如果n为偶数,那么a(n) = a(n/2) +1; 如果为奇数,那么a(n) = Min(a( (n+1)/2+2 ),   a((n-1)/2 +2 )). 算法初始化:明显a(1) = 0;

class test {

    public static void main(String[] args) {
        int k = 45;
        int[] a = new int[k + 1];
        a[1] = 1;
        char[] c = new char[k + 1];
        changeTo1(a, k, c);
        for (int i = 0; i < a.length; i++) {
            System.out.println(i + "," + c[i] + "," + a[i]);
        }
    }

    private static void changeTo1(int[] a, int k, char[] c) {
        for (int i = 2; i < a.length; i++) {
            if (i % 2 == 0) {//偶数
                a[i] = a[i / 2] + 1;
                c[i] = ‘#‘;
            } else {
                if ((a[(i + 1) / 2] + 2) > (a[(i - 1)/2] + 2)) {
                    a[i] = (a[(i - 1)/2] + 2);
                    c[i] = ‘-‘;
                } else {
                    a[i] = (a[(i + 1) / 2] + 2);
                    c[i] = ‘+‘;
                }
            }
        }
    }

}
时间: 2024-10-12 08:14:33

问对于一个给定的n,怎样才能用最少的步骤将它变到1的相关文章

程序员面试100题之十:快速找出一个数组中的两个数字,让这两个数字之和等于一个给定的值(转)

能否快速找出一个数组中的两个数字,让这两个数字之和等于一个给定的值,为了简化起见,我们假设这个数组中肯定存在至少一组符合要求的解. 假如有如下的两个数组,如图所示: 5,6,1,4,7,9,8 给定Sum= 10 1,5,6,7,8,9 给定Sum= 10 分析与解法 这个题目不是很难,也很容易理解.但是要得出高效率的解法,还是需要一番思考的. 解法一 一个直接的解法就是穷举:从数组中任意取出两个数字,计算两者之和是否为给定的数字. 显然其时间复杂度为N(N-1)/2即O(N^2).这个算法很简

JavaScript面试题:重复输出一个给定的字符串

面试题 重复输出一个给定的字符串(str第一个参数)n 次 (num第二个参数),如果第二个参数num不是正数的时候,返回空字符串. function repeatStringNumTimes(str, num) { return str; } repeatStringNumTimes("abc", 3); 提供测试情况: repeatStringNumTimes("*", 3) //应该返回 "***". repeatStringNumTime

写一个函数,对于一个给定的整数,如果它的二进制模式从正向看和反向看是一样的,那么返回true;

写一个函数,对于一个给定的整数,如果它的二进制模式从正向看和反向看是一样的,那么返回true:也就是实现这样一个函数boolean isPalindrome(int x); 分析一下,该题目主要是通过移位来实现,二进制模式从正向看和反向看是一样的,说明这个二进制数两边是对称的, 画个图看看: 代码如下: boolean isPalindrome(int x){ int flag = 1,i,j,temp;    while(1){        if(num&(0x1<<flag)){

采用truelicense进行Java规划license控制 扩展可以验证后,license 开始结束日期,验证绑定一个给定的mac住址

采用truelicense进行Java规划license控制 扩展可以验证后,license 开始结束日期,验证绑定一个给定的mac住址. Truelicense 它是一个开源java license 检验项目. 使用truelicense实现用于JAVAprojectlicense机制(包含license生成和验证)请參考http://www.it165.net/pro/html/201404/11540.html 当中包含license授权机制的原理和制作license的详细步骤 本文主要是

新手的痛苦!!!!!千辛万苦写出来代码,百般调试,就是不能实现功能,一个新手多长时间才能步入技术正规!!!

新手的痛苦!!!!!千辛万苦写出来代码,百般调试,就是不能实现功能,一个新手多长时间才能步入技术正规!!! name="<html<head lang="en"<meta charset="UTF-8"<title联动菜单title<script type="text/javascript"var area=[ ['朝阳','海淀','门头沟'], [' 淮南','淮北','合肥'], ['咸阳','西安'

PHP,Mysql-根据一个给定经纬度的点,进行附近地点查询–合理利用算法,效率提高2125倍

目前的工作是需要对用户的一些数据进行分析,每个用户都有若干条记录,每条记录中有用户的一个位置,是用经度和纬度表示的.还有一个给定的数据库,存储的是一些已知地点以及他们的经纬度,内有43W多条的数据.现在需要拿用户的经纬度和已知地点进行距离匹配,如果它们之间的距离小于一定的数据,比如说500米,就认为用户是在这个地点.MYSQL本身是支持空间索引的,但是在5.x的版本中,取消了对Distance()和Related()的支持,参考这里:MySQL 5.1参考手册 :: 19. 中的空间扩展 19.

MFC 一个类訪问还有一个类成员对象的成员变量值

作者:卿笃军 原文地址:http://blog.csdn.net/qingdujun/article/details/35263857 MFC中一个类要訪问另外一个类的的对象的成员变量值,这就须要获得原来那个类对象的指针,事实上有好几种方法都能够实现. 比方维护一个单例模式.设置静态变量等等.我们这里举个列子,实现多个类之间的相互訪问. 一.演示样例:创建MFC对话框,实现对个对话框之间数据訪问 我们创建一个MFC对话框应用程序,命名为Visitproject. 对话框本身有一个主界面(CVis

【转】重复输出一个给定的字符串的几种方法

方法1:通过 `while` 循环重复输出一个字符串 解题思路:while 语句只要指定的条件计算结果为true的时候,就执行其语句.while 语句的语法是这样的: 1 while (expression) 2 statement 在每次通过循环之前计算条件结果.如果条件为true,则执行语句.如果条件为false,则执行继续 while 循环之后的任何语句. 只要条件为true,语句就会执行. 这里是解决方案: function repeatString(str, times) { //空字

对一个给定的二维数组按照指定的键值进行排序

public function set_s(){ $arr = [ ['one' => 6,'two' => 19], ['one' => 36,'two' => 3], ['one' => 26,'two' => 3], ['one' => 2,'two' => 84], ['one' => 5,'two' => 35], ['one' => 6,'two' => 56], ['one' => 7,'two' => 7]