公众号:offer多多

V1

2022/06/19阅读:47主题:全栈蓝

算法之美第二期亚麻题

更新日期 2022-05-9

https://github.com/watchpoints/daily-interview

引言

目的:如何免费快速刷题,短时间达到 lc1000题水平,

  • 步骤1: 推荐看一本书: 别人已经把趟水了,就别为那个题目在纠结了。

    1. Jeff EricksonAlgorithms book
    2. 宫水三叶

    3 代码随想录

    1. 花花酱
  • 步骤2: 如何看:重点看他们同类型题目推荐,并不是看他们总结和答案。这个没有人能代替

然后最简单那那个题目。这个很重要,因为只要找到这个题目 后面都是扩展。

  • 步骤3:最好是leetcod 英文的 ,因为他们有同类型题目。可以代替 步骤1和步骤2.
  1. 亚麻面经 看别人考察什么 根据题目类型刷题。

https://www.1point3acres.com/bbs/thread-842588-1-1.html

https://instant.1point3acres.com/thread/842588

https://www.xiakexing.me/thread-29007-1-1.html

  1. 同类型题目 容易中等难度 环环相扣, 自己总计不出来,看看别人怎么同类型题目归纳总结的 、
  2. 提示:不是说一个一个题目刷不好,是自己无法把全部刷完,然后一个一个关联。

知识点:这次考察动态规划--子集问题 和矩阵遍历

第一题:原题 Subsequences

给了两个string,

一个searchword, 一个resultword。

问searchword在添加几个字母后,resultword能成为其 子集

举个例子吧 searchWord=“Armaze”, resultWord=“Amazon”, serchword需要添加on这两个字母后才能包含 ...


int findmin(string searchWord,string resultWord)
    {
        int sl = searchWord.size();
        int rl =resultWord.size();
        int i =0;
        int j =0;
        while(i<rl && j<sl)
        {
            if(resultWord[i] == searchWord[j])
            {
                i++;//inlcude
            }
            j++;
        }
        return sl -i; //392. 判断子序列  区别。
    }

第二题:灰度题。

给一个只包含0,1的n*m二位数组。

数组里每个点的灰度值为这个点的(每行+每列的0的数量)-(每行+每列1的数量)。

问最大的灰度值是多少。

  • https://blog.51cto.com/u_15535648/5106856
int getMaxGreyness(vector<vector<int> > &input)
{
    int rows =input.size();
    int cols =input[0].size();
    
    vector<int> myrows(rows,0);
    vector<int> mycols(cols,0);

    int res =0 ;

    for(int i =0;i<rows;i++)
    {
        for(int j =0; j<cols;j++)
        {
            if(input[i][j] == 1)
            {
                myrows[i] +=1;
            }else
            {
                myrows[i] -=1;
            }
        }
    }

    for(int j =0;j<cols;j++)
    {
        for(int i =0; i<rows;i++)
        {
            if(input[i][j] == 1)
            {
                mycols[j] +=1;
            }else
            {
                mycols[j] -=1;
            }
        }
    }

    for(int i =0;i <rows;i++)
    {
        for(int j =0;j<cols;j++)
        {
            int temp =myrows[i]+mycols[j];
            if (temp >res)
            {
                res = temp;
            }
        }
    }

    return res;
}

第一题原题举一反三。

392 判断子序列

  • https://leetcode.cn/problems/is-subsequence/

1143. 最长公共子序列(不连续)

  • 一.题目分析:

给定两个字符串 text1 和 text2,返回这两个字符串的最长 公共子序列 的长度。
如果不存在 公共子序列 ,返回 0 。

一个字符串的 子序列 是指这样一个新的字符串:
它是由原字符串在不改变字符的相对顺序的情况下删除某些字符(也可以不删除任何字符)后组成的新字符串。

例如,"ace" 是 "abcde" 的子序列,但 "aec" 不是 "abcde" 的子序列

来源:力扣(LeetCode)
链接:https://leetcode-cn.com/problems/longest-common-subsequence
著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。
  • 二. 思路分析

  • 三 . 代码实现

  1. 前置题目:判断子序列,

假如我是公共子序列 你如何判断 我是子序列.这里是后面推到最重要依据

给定字符串 s 和 t ,判断 s 是否为 t 的子序列。

  1. `f[i][j] = f[i-1][j-1] + 1 ,当text1[i] == text2[j]。

f[i][j] = max(f[i - 1][j],f[i][j - 1]),当text1[i] != text2[j]` 3.

后退
后退
  • https://leetcode-cn.com/problems/longest-common-subsequence/solution/by-flix-6gy2/
  • https://leetcode-cn.com/problems/is-subsequence/solution/dai-ma-sui-xiang-lu-dai-ni-xue-tou-dpzi-knntf/ 初始化
推到一遍
推到一遍

遍历 ace开始 遍历babcd开始

  • 第一次比较:s[0,1] = a. s2[0,1] =b. a 和b 比较 不相等,如何完成公示 ,必须依赖 什么

  • 第二次比较:s[0,1] = a. s[0,2] = b a 有一个相同的。怎么计算呢?【怎么走到这个位置的】 ‼️

  • 第三次比较:s[0,1] = a. s[0,3] = b a b 【等价于】 a 和b不相等 因此不等相加。 s1[0,0] 与s【0,3】 和 s[0,1] s2[0 3]

  • 第四比较a 与 babc

移动方向:1. 双方 同时移动 2. 一方不动,一方移动。3 一方移动 一方不动 这三个情况。

583. 两个字符串的删除操作 ✅

  • :1143. 最长公共子序列--> 392 判断子序列--->回文字串

思路 :

https://leetcode-cn.com/problems/delete-operation-for-two-strings/

首先,给定两字符 s1 和 s2,求经过多少次删除操作,可使得两个相等字符串。

该问题等价于求解两字符的「最长公共子序列」,若两者长度分别为 nn 和 mm,而最长公共子序列长度为 maxmax,则 n - max + m - maxn−max+m−max 即为答案。

作者:AC_OIer 链接:https://leetcode-cn.com/problems/delete-operation-for-two-strings/solution/gong-shui-san-xie-cong-liang-chong-xu-li-wqv7/ 来源:力扣(LeetCode) 著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。

115. 不同的子序列 hard 推到不出来 ❌

300. 最长递增子序列

旁白:思路分析 1. 画图 2.想到出过程和细节, 3. 然后写出来,4 然后朗读出来

  1. 画图

输入:nums = [10,9,2,5,3,7,101,18] 输出:4 解释:最长递增子序列是 [2,3,7,101],因此长度为 4

  1. 想到出过程和细节

  2. 然后写出来

  • 每个字符有2个可能,是子序列 ,不是子序列,2个判断,至少2个选择,不能这么判断 时间复杂度指数级级别。🙅

  • 难点 如果i>j 这2个元素递增序列,能保证一定最长的吗?

    不能,需要和前面的每个字符都判断。 --需要2次循环

  • 难点:如果i<j, 不够成 不能,需要和前面的每个字符都判断。 --需要2次循环

评价:自己分析糊涂了。 看上面的图解决

状态转移方程 位置i的最长升序子序列等于j从0到i-1各个位置的最长升序子序列 + 1 的最大值。

所以:if (nums[i] > nums[j]) dp[i] = max(dp[i], dp[j] + 1);

子序列问题是动态规划的一个重要系列,本题算是入门题目,好戏刚刚开始!

516.最长回文子序列

思路分析

1. 画图

  • https://leetcode-cn.com/problems/longest-palindromic-subsequence/

  • 花花酱 LeetCode 516. Longest Palindromic Subsequence - 刷题找工作 EP192

  • https://www.youtube.com/watch?v=g3R-pjUNa3k

2.想到出过程和细节,

  • 遍历方向
if (s[i] == s[j]) {
    dp[i][j] = dp[i + 1][j - 1] + 2; //小到大
else {
    dp[i][j] = max(dp[i + 1][j], dp[i][j - 1]);//大到小
}

3. 然后写出来,

  1. 最长回文子序列

给你一个字符串 s ,找出其中最长的回文子序列,并返回该序列的长度。

子序列定义:不改变剩余字符顺序的情况下,删除某些字符或者不删除任何字符形成的一个序列。

输入:s = "cbbd" 输出:2 解释:一个可能的最长回文子序列为 "bb" 。

输入:s = "bbbab" 输出:4 解释:一个可能的最长回文子序列为 "bbbb" 。

线索:

  1. 如果子串不是回文,就需要判断子序列是回文,选择最长回文子序列

子串怎么判断 2个for循判断

删除 与不删除 如何表示?

假如字符次s不是回文,t是s的子序列。

  • 连续 理想状态 bb
  • 不连续,中间删除几个字符。 bbbb
  • 回文子串是要连续的,回文子序列可不是连续的

bbba ===bbb --不包含a --->[start, end-1]

cbb===bb 包含b [start+1,end]

状态变化:

start 和 end 不相等情况下:

  • 不包含。 [start, end-1] --->[start,end] end-1--end
  • 包含 [start+1, end] --->[start,end] stat+1 -->start

相等情况

  • [stat+1,end-1] --->[start,end]
if (s[i] == s[j]) {
    dp[i][j] = dp[i + 1][j - 1] + 2; //小到大 
else {
    dp[i][j] = max(dp[i + 1][j], dp[i][j - 1]);//大到小 等价 
}

4 然后朗读出来

小提示: 最长回文子序列:两个字符串的「公共子序列」是这两个字符串所共同拥有的子序列。升级

公共子序列 三个移动方向
公共子序列 三个移动方向

第二题 扩展

661. 图片平滑器 []

题目:

  • https://leetcode.cn/problems/image-smoother/

  • https://leetcode.cn/problems/image-smoother/solution/by-ac_oier-nn3v/

  • https://leetcode.cn/circle/article/TeTsGw/

第三题:

https://algo.monster/problems/treasure_island_i

https://po-jen-lai.gitbook.io/coding-practice-google-high-freq/amazon/oa/treasure-island-ii

题目

You have a map that marks the location of a treasure island. 
Some of the map areas have jagged rocks and dangerous reefs. 
Other areas are safe to sail in.

There are other explorers trying to find the treasure. 
So you must figure out the shortest route to the treasure island.

Assume the map area is a two-dimensional grid, represented by a matrix of characters.

You must start from the top-left corner of the map and can move one block up, down, left, or right at a time.

The treasure island is marked as 'X' in a block of the matrix. 
'X' will not be at the top-left corner.

Any block with dangerous rocks or reefs will be marked as 'D'. You must not enter dangerous blocks. You cannot leave the map area.

Other areas 'O' are safe to sail in. The top-left corner is always safe.

Output the minimum number of steps to get to the treasure.

Input
The input consists of an argument:

matrix: a 2D string array where X represents The treasure island, D represents dangerous rocks or reefs, O represents safe to sail in areas and 'S' represents the starting point

Output
Return a number of minimum step for route

Examples
Example 1:
Input:
matrix = [
  ['O''O''O''O'],
  ['D''O''D''O'],
  ['O''O''O''O'],
  ['X''D''D''O'],
]
Output: 5
Explanation:
Route is (0, 0), (0, 1), (1, 1), (2, 1), (2, 0), (3, 0) The minimum route takes 5 steps.

原文:

  1. 通过dfs遍历 然后到目标 这个路径存在多个,选择最短的一个。全局变量。

递归回溯: 只能搜索2^n种情况。所以就是O(2^n).基本上回溯法就是两种复杂度,指数或者阶乘。 不适合。

n皇后问题如果不进行任何剪枝,以最朴素的观点来看,其时间复杂度就是 [公式] 。因为 N 行N 列,皇后的排列方式共有 [公式] 种。

  1. 非递归遍历
from typing import List

def routeStep(matrix: List[List[str]]) -> int:
    from collections import deque
    num_rows = len(matrix)
    num_cols = len(matrix[0])

    def get_neighbors(coord):
        row, col = coord
        for dx, dy in [(-1, 0), (0, -1), (1, 0), (0, 1)]:
            r = row + dx
            c = col + dy
            if 0 <= r < num_rows and 0 <= c < num_cols and matrix[r][c] != 'D':
                yield (r, c)

    def bfs(start):
        queue = deque([start])
        r, c = start
        matrix[r][c] = ' '
        dist = 0
        while len(queue) > 0:
            dist += 1
            n = len(queue)
            for _ in range(n):
                node = queue.popleft()
                for r, c in get_neighbors(node):
                    if matrix[r][c] == 'X':
                        return dist
                    if matrix[r][c] == ' ':
                        continue
                    queue.append((r, c))
                    matrix[r][c] = ' '
    return bfs((0, 0))

if __name__ == "__main__":
    rows = int(input())
    matrix = [[x for x in input().split()] for _ in range(rows)]
    result = routeStep(matrix)
    print(result

第四题 200. Number of Islands ✅

https://leetcode.com/problems/number-of-islands/ 原文: 这个题目 不好,没有体现本质 死循环处理 通过 自身变量

第五题:329. 矩阵中的最长递增路径 ✅

1.直观

给定一个 m x n 整数矩阵 matrix ,找出其中 最长递增路径 的长度。

https://leetcode.cn/problems/longest-increasing-path-in-a-matrix/

  1. 思路和细节
  • 难点1: 最长递增路径。是找到一个路径,然后计算长度。这个很难。直接无解了。 需要观察规律。变化的规律。 ---比较大小

  • 难点2:遍历 方向 这里 通过大小 避免死循环。

  • 难点3:函数参数 ,递增怎么体现。大于上个节点。

  1. 原文
  • 数据结构是图,这里不是固定一个节点开始,从任意节点开始(孤岛问题 不是都是连续递增的)
  • 假设存在这个路径,路径特点 是递增 (tree的高度 是依赖+1), 这个路径计算过程中,
  • 图的深度搜索遍历。
  • 如何防止死循环呢。 vector<vector > dp(rows,vector (cols,1));不能阻止。 因为这个结果 还没有计算完毕时候就发生思想循环。 1 --2
    • 误导:这跟不上dp[i][j] 访问过可以直接使用它么数值。必须递增 递增。
  • 通过大小 防止死循环,根据递增访问的 不可能有回头路。

小帖士: 矩阵中的最长递增路径 改为最短路径 如何计算呢? 非递归版本:

  • 方法二:拓扑排序
  • https://leetcode.cn/problems/longest-increasing-path-in-a-matrix/solution/ju-zhen-zhong-de-zui-chang-di-zeng-lu-jing-by-le-2/

第六题

  1. https://programmercarl.com/0968.%E7%9B%91%E6%8E%A7%E4%BA%8C%E5%8F%89%E6%A0%91.html

516.最长回文子序列

知识点:动态规划

公司:百度:

题目描述

给你一个字符串 s ,找出其中最长的回文子序列,并返回该序列的长度。

子序列定义为:不改变剩余字符顺序的情况下,删除某些字符或者不删除任何字符形成的一个序列。

来源:力扣(LeetCode) 链接:https://leetcode.cn/problems/longest-palindromic-subsequence

思路描述

/旁白:1. 画图 2.想到出过程和细节,3. 然后写出来,4 然后朗读出来。

回文子串是要连续的,回文子序列可不是连续的!

回文子串,回文子序列都是动态规划经典题目。

回文子串,可以做这两题:

647.回文子串 5.最长回文子串 思路其实是差不多的,但本题要比求回文子串简单一点,因为情况少了一点

动规五部曲分析如下:

1,确定dp数组(dp table)以及下标的含义 dp[i][j]:字符串s在[i, j]范围内最长的回文子序列的长度为dp[i][j]。

  1. 确定递推公式 在判断回文子串的题目中,关键逻辑就是看s[i]与s[j]是否相同。

如果s[i]与s[j]不相同,说明s[i]和s[j]的同时加入 并不能增加[i,j]区间回文子串的长度,那么分别加入s[i]、s[j]看看哪一个可以组成最长的回文子序列。

加入s[j]的回文子序列长度为dp[i + 1][j]。

加入s[i]的回文子序列长度为dp[i][j - 1]。

那么dp[i][j]一定是取最大的,即:dp[i][j] = max(dp[i + 1][j], dp[i][j - 1]);

分类:

后端

标签:

后端

作者介绍

公众号:offer多多
V1