【算法】day03:动态规划dp

努力经营当下,直至未来明朗!


普通小孩也要热爱生活!

1. 青蛙跳台阶

跳台阶
1)思路:如果青蛙在第n个台阶上,那么它要么来自n-1阶,要么来自n-2阶。(因为一次跳1 or 2级台阶)
2)动态规划dp问题
① 定义状态; ② 编写状态方程; ③ 设置初始值
3)详细分析:
① f(n): 青蛙跳上第n级台阶的总跳法数 [定义状态]
②青 蛙跳到n级台阶的方法:要么直接从n-1跳,要么从n-2跳;但是n-2跳到n有两种方式:直接跳or从n-1跳,即:n-1到n-2的就被包含在n-1中
③ 所以:f(n) = f(n-1) + f(n-2) [转移方程]
④ f(0)=1; f(1)=1; f(2)=2; [设置初始值]
⑤ 注意:数组长度=目标台阶+1(从0开始的)
4)补充:一般使用动归,必定使用数组(一维or二维)

代码:
① 递归

public class Solution {
    public int jumpFloor(int target) {
        // 使用递归
        // 定义一个数组:数组长度!!
        int[] dp = new int[target+1];
        dp[0] = 1;
        dp[1] = 1;

        // 循环求跳法
        for(int i=2; i<=target; i++) {
            dp[i] = dp[i-1] + dp[i-2];
        }

        return dp[target];
    }
}

② 迭代(fib)

public class Solution {
    public int jumpFloor(int target) {
        // 使用迭代(fib类似)
        int first = 1;
        int second = 1;
        int third = 1;
        
        // 循环求跳数
        while(target >= 2) {
            third = first + second;
            first = second;
            second = third;
            target--;
        }

        return third;
    }
}

2. 矩形覆盖

矩形覆盖
1)思路:
① 覆盖要么是横着覆盖,要么是竖着覆盖。
② n个小矩形覆盖:要么最后一个竖着放(到n-1),要么最后两个横着放(到n-2)。
2)代码

public class Solution {
    public int rectCover(int target) {
        // 类似于fib
        // f(n) = f(n-1) + f(n-2)
        // 一定不要忘记这个,否则运行失败!
        if(target < 2) {
            return target;
        }

        // 注意数组长度!
        int[] dp = new int[target+1];
        // 初始化:
        dp[0] = 0;
        dp[1] = 1;
        dp[2] = 2;
        for(int i=3; i<=target; i++) {
            dp[i] = dp[i-1] + dp[i-2];
        }

        return dp[target];
    }
}


3. 二进制中1的个数

二进制中1的个数
1)二进制表示一定要体现出其数据类型的位数。如int,则二进制就需要32位来表示
2)思路:

① 按位与+左移/右移,但是不太推荐(如果0太多,无效检测就会增加);
② x&(x-1),直到为0,按位与的次数就是所求x中1的个数(推荐使用

3)代码:

public class Solution {
    public int NumberOf1(int n) {
        int count = 0;
        while(n != 0) {
            n &= (n-1);
            count++;
        }
        return count;
    }
}


4. 链表中倒数第k个结点

链表中倒数第k个结点
1)思路:定义“前后指针”,前指针front先走k步,然后前后指针同时开始走,直到front走完遇到null,此时尾指针rear所在位置就是倒数第k个结点
2)代码:

/*
public class ListNode {
    int val;
    ListNode next = null;

    ListNode(int val) {
        this.val = val;
    }
}*/
public class Solution {
    public ListNode FindKthToTail(ListNode head,int k) {
        // 首先进行判断
        if(head==null || k<0) {
            return null;
        }

        // 定义前后指针
        ListNode front = head;
        ListNode rear = head;

        // 开始进行走k步
        while(k>0 && front!=null) {
            front = front.next;
            k--;
        }

        // 同时开始走,直到front==null
        while(front != null) {
            front = front.next;
            rear = rear.next;
        }

        // 注意这里结束的判断条件!!
        return (k>0)? null:rear;
    }
}

yy

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

'Dream是普通小孩耶

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值