【算法入门级训练】 - DAY3

动规篇



前言

本次算法入门训练主要训练以下三个内容:

  1. 以特殊数据结构为载体的算法结构,比如:数组、链表、栈、二叉树等
  2. 以考察常见算法思想基础的算法题,比如:动态规划、贪心、回溯等
  3. 基于某种场景包装下的1和2

提示:以下是本篇文章正文内容

内容

第一题:跳台阶

解题思路:简单dp跟昨天的fib数列解题思路差不多,为了入门并熟悉动态规划做准备。
OJ链接:第一题

public class Solution {
    public int jumpFloor(int target) {
        //dp
        //跳到第n阶台阶,只有两种到法,从第n-2阶台阶开始跳or从第n-1阶台阶开始跳
        //定义状态:f(n):第n阶台阶的跳法
        //状态转移方程: f(n) = f(n-1) + f(n-2)
        //设置初始值:f(1) = 1 f(2) = 2 f(0) = 1;
        if(target < 2){
            return 1;
        }
        //从0阶 - target阶
        int[] dp = new int[target+1];
        dp[0] = 1;
        dp[1] = 1;
        dp[2] = 2;
        for(int i = 3; i <= target; i++){
            dp[i] = dp[i-1] + dp[i-2];
        }
        return dp[target];
    }
}

第二题:矩形覆盖

解题思路:两种放法竖着放和横着放,注意横着放时你下次的放法也就确定了,我们继续使用dp来处理。
OJ链接:第二题

public class Solution {
    public int rectCover(int target) {
        //简单dp
        //定义状态:f(n):n个2*1的小矩形组成2*n的大矩形的方法
        //设置状态转移方程: f(n) = f(n-1)[竖着放] + f(n-2)[横着放]
        //定义初始值:f(1) = 1 f(2) = 2 f(0) = 0 (不考虑0);
        if(target == 0){
            return 0;
        }
        if(target == 1 || target == 2){
            return target;
        }
        int[] dp = new int[target+1];
        dp[1] = 1;
        dp[2] = 2;
        for(int i = 3; i <= target; i++){
            dp[i] = dp[i-1] + dp[i-2];
        }
        return dp[target];
    }
}

第三题:二进制中1的个数

解题思路:了解 x & (x-1) -> 消除x二进制的最低为1的位,这题就会了且是最优解。
OJ链接:第三题

public class Solution {
    public int NumberOf1(int n) {
        // x & (x-1)  -> 消除x二进制的最低为1的位
        int count = 0;
        while(n != 0){
            n &= n-1;
            count++;
        }
        return count;
    }
}

第四题:链表中倒数第k个结点

解题思路:非常简单很多经典的链表题,要了解快慢指针和走差值步。
OJ链接:第四题

/*
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;
        }
        //快慢指针
        //1.先让快指针走k步
        ListNode fast = head;
        ListNode slow = head;
        while (k > 0) {
            if (fast == null) {
                //k大于链表的长度
                return null;
            }
            fast = fast.next;
            k--;
        }
        //2.再让两个指针同时走,快指针走完,慢指针就是倒数第k个节点
        while (fast != null) {
            fast = fast.next;
            slow = slow.next;
        }
        return slow;
    }
}


总结

以上就是今天训练的内容,主要是为了入门动态规划,动态规划的本质就是记录了前一次结果,然后由小问题推及大问题,但是什么题什么时候使用动态规划,还需要大量做题来感悟。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值