【算法刷题】Day19

文章目录

  • 1. 山脉数组的峰顶索引
    • 题干:
    • 算法原理:
    • 代码:
  • 2. 寻找峰值
    • 题干:
    • 算法原理:
      • 1. 暴力解法
      • 2. 二分查找
    • 代码:
  • 3. 下降路径最小和
    • 题干:
    • 算法原理:
      • 1. 状态表示
      • 2.状态转移方程
      • 3. 初始化
      • 4. 填表顺序
      • 5. 返回值
    • 代码:

1. 山脉数组的峰顶索引

【算法刷题】Day19_第1张图片
【算法刷题】Day19_第2张图片
原题链接


题干:

山脉数组
找峰顶 返回索引
【算法刷题】Day19_第3张图片

算法原理:

【算法刷题】Day19_第4张图片
由于这个数组具有“二段性”,使用二分查找
目标是左边的:左边小于右边
目标值右边的:左边大于右边

  • 峰顶数据特点: arr[i] > arr[i - 1] && arr[i] > arr[i + 1]
  • 峰顶左边的数据特点: arr[i] > arr[i - 1] && arr[i] < arr[i + 1] ,也就是呈现上升趋势
  • 峰顶右边数据的特点: arr[i] < arr[i - 1] && arr[i] > arr[i + 1] ,也就是呈现下降趋势

【算法刷题】Day19_第5张图片

  • 如果 mid 置呈现上升趋势,说明我们接下来要在 [mid + 1, right] 区间继续搜索
  • 如果 mid 位置呈现下降趋势,说明我们接下来要在 [left, mid - 1] 区间搜索
  • 如果 mid 位置就是⼭峰,直接返回结果

代码:

class Solution {
    public int peakIndexInMountainArray(int[] arr) {
        int left = 1;
        int right = arr.length - 2;
        while(left < right) {
            int mid = left + (right - left +1) / 2;
            if(arr[mid] > arr[mid - 1]) {
                left = mid;
            }else {
                right = mid - 1;
            }
        }
        return left;
    }
}

【算法刷题】Day19_第6张图片


2. 寻找峰值

【算法刷题】Day19_第7张图片
原题链接


题干:

峰值元素:严格大于左右相邻的元素

算法原理:

首先,这道题有三种情况
【算法刷题】Day19_第8张图片

1. 暴力解法

从第一个位置开始,一直向后走
分情况讨论

2. 二分查找

【算法刷题】Day19_第9张图片
任取⼀个点 i ,与下⼀个点 i + 1 ,会有如下两种情况:

  • arr[i] > arr[i + 1] :此时「左侧区域」⼀定会存在⼭峰(因为最左侧是负无穷),那么我们可以去左侧去寻找结果
  • arr[i] < arr[i + 1] :此时「右侧区域」⼀定会存在⼭峰(因为最右侧是负无穷),那么我们可以去右侧去寻找结果
    【算法刷题】Day19_第10张图片
    接下来按照模版写就可以

代码:

class Solution {
    public int findPeakElement(int[] nums) {
        int left = 0;
        int right = nums.length - 1;
        while(left < right) {
            int mid = left + (right - left) / 2;
            if(nums[mid] < nums[mid + 1]) {
                left = mid + 1;
            }else {
                right = mid;
            }
        }
        return left;
    }
}

【算法刷题】Day19_第11张图片


3. 下降路径最小和

【算法刷题】Day19_第12张图片
【算法刷题】Day19_第13张图片
【算法刷题】Day19_第14张图片
原题链接


题干:

有一个 n * n 的整形数组
找到下降路径的最小和
【算法刷题】Day19_第15张图片
比如示例一,就有两种情况
1 可以向下、向左下、向右下

算法原理:

1. 状态表示

dp[i][j] 表示:到达 [i, j] 位置时,所有下降路径中的最小和

2.状态转移方程

【算法刷题】Day19_第16张图片
对于普遍位置 [i, j] ,根据题意得,到达 [i, j] 位置可能有三种情况:

  1. 从正上方 [i - 1, j] 位置转移到 [i, j] 位置
  2. 从左上方 [i - 1, j - 1] 位置转移到 [i, j] 位置
  3. 从右上方 [i - 1, j + 1] 位置转移到 [i, j] 位置

我们要的是三种情况下的「最小值」,然后再加上矩阵在 [i, j] 位置的值
dp[i][j] = min(dp[i - 1][j], min(dp[i - 1][j - 1], dp[i - 1][j +1])) + matrix[i][j]

3. 初始化

可以在最前⾯加上⼀个「辅助结点」,帮助我们初始化

  • 辅助结点里面的值要「保证后续填表是正确的」
  • 「下标的映射关系」

在本题中,需要「加上⼀行」,并且「加上两列」
所有的位置都初始化为无穷大,然后将第⼀行初始化为 0 即可

4. 填表顺序

从上往下

5. 返回值

返回「dp表中最后⼀行的最小值」


代码:

class Solution {
    public int minFallingPathSum(int[][] matrix) {
        int n = matrix.length;
        int[][] dp = new int[n + 1][n + 2];
        for(int i = 1; i <= n; i++) {
            dp[i][0] = dp[i][n + 1] = Integer.MAX_VALUE;
        }
        for(int i = 1; i <= n; i++) {
            for(int j = 1; j <= n; j++) {
                dp[i][j] = Math.min(dp[i-1][j], Math.min(dp[i-1][j-1],dp[i-1][j+1])) + matrix[i-1][j-1];
            }
        }
        int ret = Integer.MAX_VALUE;;
        for(int j = 1; j <= n; j++) {
            ret = Math.min(ret, dp[n][j]);
        }
        return ret;
    }
}

【算法刷题】Day19_第17张图片

你可能感兴趣的:(算法刷题,算法,java,动态规划,二分查找)