• 博客园logo
  • 会员
  • 周边
  • 新闻
  • 博问
  • 闪存
  • 众包
  • 赞助商
  • Chat2DB
    • 搜索
      所有博客
    • 搜索
      当前博客
  • 写随笔 我的博客 短消息 简洁模式
    用户头像
    我的博客 我的园子 账号设置 会员中心 简洁模式 ... 退出登录
    注册 登录

无信不立

  • 博客园
  • 联系
  • 订阅
  • 管理

公告

View Post

【数据结构和算法】动态规划爬楼梯和字符串转数字算法

一、将一个字符串转换为数字,返回类型为int类型

* "123"->123
* "1.0"->1
* "123abc456"->0
* "123123123123123"->2147483647
* "-35432343242342342"->-2147483648

题解地址:https://leetcode-cn.com/problems/string-to-integer-atoi/solution/jin-liang-bu-shi-yong-ku-han-shu-nai-xin-diao-shi-/

这个问题其实没有过多的技巧,考察的是细心和耐心,并且需要不断地调试。在这里我简单罗列几个要点。

Java 、Python 和 C++ 字符串的设计都是不可变的,即使用 trim() 会产生新的变量,因此我们尽量不使用库函数,使用一个变量 index 去做线性遍历,这样遍历完成以后就得到转换以后的数值。

根据示例 1,需要去掉前导空格;
根据示例 2,需要判断第 1 个字符为 + 和 - 的情况,因此,可以设计一个变量 sign,初始化的时候为 1,如果遇到 - ,将 sign 修正为 -1;
判断是否是数字,可以使用字符的 ASCII 码数值进行比较,即 0 <= c <= '9';
根据示例 3 和示例 4 ,在遇到第 1 个不是数字的字符的情况下,就得退出循环;
根据示例 5,如果转换以后的数字超过了 int 类型的范围,需要截取。这里需要将结果 res 变量设计为 long 类型,注意:由于输入的字符串转换以后也有可能超过 long 类型,因此需要在循环内部就判断是否越界,只要越界就退出循环,这样也可以减少不必要的计算;
因为涉及下标访问,因此全程需要考虑数组下标是否越界的情况。
特别注意:

public class Solution {

    public int myAtoi(String str) {
        int len = str.length();

        // 去除前导空格
        int index = 0;
        while (index < len) {
            if (str.charAt(index) != ' ') {
                break;
            }
            index++;
        }

        if (index == len) {
            return 0;
        }

        // 第 1 个字符如果是符号,判断合法性,并记录正负
        int sign = 1;
        char firstChar = str.charAt(index);
        if (firstChar == '+') {
            index++;
            sign = 1;
        } else if (firstChar == '-') {
            index++;
            sign = -1;
        }

        // 不能使用 long 类型,这是题目说的
        int res = 0;
        while (index < len) {
            char currChar = str.charAt(index);
            // 判断合法性
            if (currChar > '9' || currChar < '0') {
                break;
            }

            // 题目中说:环境只能存储 32 位大小的有符号整数,因此,需要提前判断乘以 10 以后是否越界
            if (res > Integer.MAX_VALUE / 10 || (res == Integer.MAX_VALUE / 10 && (currChar - '0') > Integer.MAX_VALUE % 10)) {
                return Integer.MAX_VALUE;
            }
            if (res < Integer.MIN_VALUE / 10 || (res == Integer.MIN_VALUE / 10 && (currChar - '0') > -(Integer.MIN_VALUE % 10))) {
                return Integer.MIN_VALUE;
            }

            // 每一步都把符号位乘进去
            res = res * 10 + sign * (currChar - '0');
            index++;
        }

        return res;
    }
}
View Code

 

 

二、假设你正在爬楼梯。需要 n 阶你才能到达楼顶。 每次你可以爬 1 或 2 个台阶。你有多少种不同的方法可以爬到楼顶呢

今天我们来爬一爬楼梯。
假设你正在爬楼梯。需要 n 阶你才能到达楼顶。

每次你可以爬 1 或 2 个台阶。你有多少种不同的方法可以爬到楼顶呢?

注意:给定 n 是一个正整数。

示例 1:

输入: 2
输出: 2
解释: 有两种方法可以爬到楼顶。

1 阶 + 1 阶
2 阶

 

示例 2:
输入: 3
输出: 3

解释: 有三种方法可以爬到楼顶。
1. 1 阶 + 1 阶 + 1 阶
2. 1 阶 + 2 阶
3. 2 阶 + 1 阶

 

其实多数几组你就会发现规律
一阶楼梯:1种方法
两阶楼梯:2种方法
三阶楼梯:3种方法
四阶楼梯:5种方法
五阶楼梯:8种方法
六阶楼梯:13种方法
朋友们应该看出来了有规律了 这不就是斐波那契数列么,只不过缺少第一项而已。

Clipboard_Screenshot_1755852808

package obj.sf;

public class Stairs {

    public static void main(String[] args) {
        System.out.println(calculateStairs(20));
    }

    /**
     * @param n
     * @return
     */
    public static long calculateStairs(int n) {
        //当只有一个台阶 和两个台阶时,方案数是明确的
        if (n == 1) {
            return 1;
        }
        if (n == 2) {
            return 2;
        }

        //当台阶数大于2个台阶,则声明dp
        //数组下标表示台阶数,数组中填充的值表示方案
        long[] dp = new long[n + 1];
        dp[0] = 0;//0个台阶的方案数是0
        dp[1] = 1;//1个台阶数方案是1
        dp[2] = 2;//2个台阶的方案数2
        //依次从第三个台阶计算每个台阶数的方案
        for (int i = 3; i <= n; i++) {
            dp[i] = dp[i - 1] + dp[i - 2];
        }
        return dp[n];
    }
}
View Code

 

posted on 2020-02-24 09:09  无信不立  阅读(194)  评论(0)    收藏  举报

刷新页面返回顶部
 
博客园  ©  2004-2026
浙公网安备 33010602011771号 浙ICP备2021040463号-3