Java 算法题笔记(五)

本文深入探讨了爬楼梯问题的两种解决方法:动态规划与递归优化,以及二进制字符串求和的实现细节。通过具体示例,展示了算法的设计思路与代码实现,适合算法初学者与面试备考者。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

爬楼梯

假设你正在爬楼梯。需要 n 阶你才能到达楼顶。

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

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

示例 1:

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

示例 2:

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

动态规划

爬上第n 层楼梯,是一般有两种方法,第n-1 层爬一层到达,或者是第n-2 层爬两层到达,以此类推,再算出第n-1 层与第n-2 的层,所以可以用递归,但是反过来的递推效率更高,即前面可知第n 层可以由第n-2 层与第n-1 层,然后不断算到第n 层。

public int climbStairs(int n) {
        if (n < 1) return 0;

        if (n == 1) return 1;

        if (n == 2) return 2;

        int count = 3;
        int a=1;
        int b=2;
        int sum = 0;
        while (count <= n){
            sum = a+b;
            a = b;
            b = sum;
            count++;
        }
        return sum;
    }

法二

递归超时,所以加入map ,把算过的存一下,如果再用到就不算了,节省性能开销,提高效率。

Map<Integer,Integer> map = new HashMap<>();
    
    public int climbStairs(int n) {
        if (n < 1) return 0;

        if (n == 1) return 1;

        if (n == 2) return 2;

        if (map.containsKey(n)){
            return map.get(n);
        }else {
            int v = climbStairs(n-1)+climbStairs(n-2);
            map.put(n,v);
            return v;
        }
    }

二进制求和

给定两个二进制字符串,返回他们的和(用二进制表示)。

输入为非空字符串且只包含数字 1 和 0

示例 1:

输入: a = "11", b = "1"
输出: "100"

示例 2:

输入: a = "1010", b = "1011"
输出: "10101"
public String addBinary(String a, String b) {
        int len_a = a.length();
        int len_b = b.length();
        int len = (len_a > len_b ? len_a : len_b) + 1; // 这个+1 是为进位准备的
        int[] t_a = new int[len];
        int i = 0;
        for (i = 0; i < len_a; i++){
            // len - len_a 找到应该填充的起始位置,然后 + i 是从0 开始,逐个往后将值赋上
            t_a[i + len - len_a] = Integer.parseInt(a.charAt(i) + "");
        }
        int[] t_b = new int[len];
        for (i = 0; i < len_b; i++){
            t_b[i + len - len_b] = Integer.parseInt(b.charAt(i) + "");
        }
        int temp = 0; // 进位值,进位的话该值为1
        int[] res = new int[len];
        for (i = len-1;i >= 0;i--){
            res[i] = getResult(t_a[i],t_b[i],temp);
            temp = getTemp(t_a[i],t_b[i],temp);
        }
        StringBuilder sb = new StringBuilder();
        for (i = 0; i < len; i++){
            // 找到开始位为1 的
            if (res[i] == 1){
                for (int j = i; j< len ;j++){
                    sb.append(res[j]);
                }
                break;
            }
        }
        if (i == len)
            return "0";
        return sb.toString();
    }

    /**
     * 由二进制相加的特点
     */
    public int getResult(int i, int j, int temp) {
        return i ^ j ^ temp;
    }


    /**
     * 获取进位值0,1 都不进位,所以返回0
     * > 1 才进位
     */
    public int getTemp(int i, int j, int temp) {
        if (i + j + temp > 1)
            return 1;
        return 0;
    }

旋转数组

给定一个数组,将数组中的元素向右移动 个位置,其中 是非负数。

示例 1:

输入: [1,2,3,4,5,6,7] k = 3输出: [5,6,7,1,2,3,4]
解释:
向右旋转 1 步: [7,1,2,3,4,5,6]

向右旋转 2 步: [6,7,1,2,3,4,5]
向右旋转 3 步: [5,6,7,1,2,3,4]

示例 2:

输入: [-1,-100,3,99] 和 k = 2
输出: [3,99,-1,-100]
解释: 
向右旋转 1 步: [99,-1,-100,3]
向右旋转 2 步: [3,99,-1,-100]

取模运算

public void rotate(int[] nums, int k) {
       int[] temp = new int[nums.length];
        for (int i=0;i<nums.length;i++){
            int index = (i+k)%nums.length;
            temp[index] = nums[i];
        }
        System.arraycopy(temp, 0, nums, 0, nums.length);
    }

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值