【算法刷题】Day16

1. 不同路径

在这里插入图片描述
在这里插入图片描述
原题链接


题干:

机器人只能向下和向右走,不能回退(向上或者向左)


算法原理:

  1. 状态表示
    经验 + 题目要求
    以[ i,j ] 为结尾时…
    dp[i][j] 表示:走到 [i, j] 位置处,⼀共有多少种方式
  2. 状态转移方程
    最近的一步 划分问题
    在这里插入图片描述
    因为只能从上面或者左边走到这个位置
    所以
    从 [i, j] 位置的上方( [i - 1, j] 的位置)向下走一步,转移到 [i, j] 位置
    从 [i, j] 位置的左方( [i, j - 1] 的位置)向右走⼀步,转移到 [i, j] 位置
    在这里插入图片描述
    不过,这里走的是一步,而不是一次
    所以并不是上一步+1,而是直接加上下一步可能得次数
    dp[i][j] = dp[i - 1][j] + dp[i][j - 1]
  3. 初始化
    这里我们依然要使用虚拟节点来写
    不过,这里我们要做到以下两点:
    (1)虚拟节点里面的值,要保证后面填表的结果正确
    (2)下标的映射
    这里最重要的就是第一点
    在这里插入图片描述
    在这里,因为求的第一行的值都是 1
    这里就需要第一行第一列上面的虚拟节点为 1
  4. 填表顺序
    从上往下填写每一行
    每一行从左往右填写
  5. 返回值
    dp[m][n]

代码:

class Solution {
   
    public int uniquePaths(int m, int n) {
   
        //1.创建dp 表
        //2.初始化
        //3.填表
        //4.返回值

        int[][] dp = new int [m + 1][n + 1];
        dp[0][1] = 1;
        for(int i = 1; i <= m; i ++) {
   //从上往下每一行
            for(int j = 1; j <= n; j++) {
   //从左往右填写每一行
                dp[i][j] = dp[i - 1][j] + dp[i][j - 1];
            }
        }
        return dp[m][n]; 
    }
}

在这里插入图片描述

2. 二分查找

在这里插入图片描述
原题链接


题干:

n 个元素有序的数组,找到 target,返回下标

算法原理:

1、暴力解法 O(n)

从头开始遍历,遇到 target 返回

2、二分查找算法

使用“二分查找”,在遇到“二段性”的时候可用
在一个数组中,拿到目标值 在数组中查找,发现可以划分为两端的区域
并且可以选择性的舍去一段,在另一段进行查找
这个时候就可以使用
(二分查找并不一定在有序数组,满足“二段性”就可用)

  1. 定义 left ,right 指针,分别指向数组的左右区间
  2. 找到待查找区间的中间点 mid ,找到之后分三种情况讨论:
    (1)arr[mid] == target 说明正好找到,返回 mid 的值
    (2)arr[mid] > target 说明 [mid, right] 这段区间都是⼤于 target 的,因此舍去右边区间,在左边 [left, mid -1] 的区间继续查找,即让 right = mid -1 ,然后重复 2 过程
    (3)arr[mid] < target 说明 [left, mid] 这段区间的值都是⼩于 target 的,因此舍去左边区间,在右边 [mid + 1, right] 区间继续查找,即让 left = mid +1 ,然后重复 2 过程
  3. 当 left 与 right 开时,说明整个区间都没有这个数,返回 -1

看图也可
在这里插入图片描述


细节问题:

  1. 循环结束的条件
    left > right
  2. 为什么是正确的
    虽然比较的次数少,但是与暴力解法相似,因此结果是正确的
  3. 时间复杂度
    long(n)
    在这里插入图片描述

朴素二分模版:

        while(left <= right) {
   
            int mid = left + (right - left) / 2;//防止溢出
            if(......) {
   
                left = mid + 1;
            }else if(......) {
   
                right = mid - 1;
            }else{
   
                return ......;
            }
        }

代码:

class Solution {
   
    public int search(int[] nums, int target) {
   
        int left = 0;
        int right = nums.length - 1;
        while(left <= right) {
   
            int mid = left + (right - left) / 2;//为了防止溢出问题
            if(nums[mid] < target) {
   
                left = mid + 1;
            }else if(nums[mid] > target) {
   
                right = mid - 1;
            }else{
   
                return mid;
            }
        }
        return -1;
    }
}

在这里插入图片描述

相关推荐

  1. 算法day10

    2023-12-19 10:00:05       47 阅读
  2. 算法day11

    2023-12-19 10:00:05       51 阅读
  3. 算法day12

    2023-12-19 10:00:05       58 阅读
  4. 算法day14

    2023-12-19 10:00:05       55 阅读
  5. 算法day15

    2023-12-19 10:00:05       60 阅读

最近更新

  1. docker php8.1+nginx base 镜像 dockerfile 配置

    2023-12-19 10:00:05       98 阅读
  2. Could not load dynamic library ‘cudart64_100.dll‘

    2023-12-19 10:00:05       106 阅读
  3. 在Django里面运行非项目文件

    2023-12-19 10:00:05       87 阅读
  4. Python语言-面向对象

    2023-12-19 10:00:05       96 阅读

热门阅读

  1. 怎么有效防护服务器被入侵

    2023-12-19 10:00:05       53 阅读
  2. 第二百一十四回

    2023-12-19 10:00:05       58 阅读
  3. React中渲染html结构---dangerouslySetInnerHTML

    2023-12-19 10:00:05       69 阅读
  4. Linux中命令添加-r的作用

    2023-12-19 10:00:05       66 阅读
  5. 理解并实现C语言中的strcpy函数

    2023-12-19 10:00:05       59 阅读
  6. Docker容器与JVM比较

    2023-12-19 10:00:05       76 阅读
  7. 华为数通试题

    2023-12-19 10:00:05       51 阅读
  8. LeetCode算法练习top100:(9)栈和堆

    2023-12-19 10:00:05       59 阅读
  9. 【无标题】

    2023-12-19 10:00:05       54 阅读
  10. 高德地图路线规划途径点vue3

    2023-12-19 10:00:05       67 阅读
  11. Flink 数据类型 & TypeInformation信息

    2023-12-19 10:00:05       54 阅读