IT数码 购物 网址 头条 软件 日历 阅读 图书馆
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
图片批量下载器
↓批量下载图片,美女图库↓
图片自动播放器
↓图片自动播放器↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁
 
   -> 数据结构与算法 -> JS:三大算法 day1 -> 正文阅读

[数据结构与算法]JS:三大算法 day1

回溯、贪心、动态规划的思路是通过大量做题培养的,不是说几天就能掌握,而且题目不会告诉你使用哪个算法。坚持做题。。。

回溯——46. 全排列(中等) 51.N皇后 (困难)

前序遍历的代码在进入某一个节点之前的那个时间点执行,后序遍历代码在离开某个节点之后的那个时间点执行。 「路径」和「选择」是每个节点的属性

def backtrack(路径, 选择列表):
	if 满足结束条件:
        result.add(路径)
        return
	for 选择 in 选择列表:
	    # 做选择
	    将该选择从选择列表移除
	    路径.add(选择)
	    backtrack(路径, 选择列表)
	    # 撤销选择
	    路径.remove(选择)
	    将该选择再加入选择列表

这里稍微做了些变通,没有显式记录「选择列表」,而是通过 used 数组记录 track 中的元素,从而推导出当前的选择列表。
在这里插入图片描述

JS语法——复制数组
[…path]
Array.from(path)
path.slice()

46 题
记住最简单的框架

var permute = function(nums) {
    let used = new Array(nums.length).fill(false)
    let res = [], track = []
    function backtrack(nums, track, used) {
        if(track.length == nums.length) {
            res.push([...track])
            return
        }
        for(let i=0; i<nums.length; i++) {
            if(used[i]) continue
            track.push(nums[i])
            used[i] = true
            backtrack(nums, track, used)
            track.pop()
            used[i] = false
        }
    }
    backtrack(nums, track, used)
    return res;
};

无非是改改做选择的方式,排除不合法选择的方式而已。

每一种解法包含一个不同的 n 皇后问题 的棋子放置方案,该方案中 ‘Q’ 和 ‘.’ 分别代表了皇后和空位。
在这里插入图片描述

难度在于返回要求格式,文章的路径为二维数组,我使用一维代替。考验JS语法。对map方法的了解。

51题代码

var isValid = (row, col, track) => {
    for(let i=0; i<row; i++) {
        if(track[i]==col || Math.abs(track[i] - col) / (row - i) == 1) return false
    }
    return true
}
function transform(track) {
    let n = track.length
    let board = new Array(n).fill(0).map(() => new Array(n).fill('.'))
    for(let i=0; i<n; i++) board[i][track[i]] = 'Q'
    // 不会改变原始数组
    return board.map((val) => val.join(""))
}
var solveNQueens = function(n) {
    let res = [], track = []
    function backtrack(track, row) {
        // 不是n-1
        if(row == n) {
            res.push(transform(track))
            return
        }
        for(let col = 0; col < n; col++) {
            if(!isValid(row, col, track)) continue
            track.push(col)
            backtrack(track, row+1)
            track.pop()
        }
    }
    backtrack(track, 0)
    return res;
};

文章总结

其实回溯算法其实就是我们常说的 DFS 算法,本质上就是一种暴力穷举算法

写 backtrack 函数时,需要维护走过的「路径」和当前可以做的「选择列表」,当触发「结束条件」时,将「路径」记入结果集。

有的时候,我们并不想得到所有合法的答案,只想要一个答案,怎么办呢?
第二个return,不在继续找「选择列表」
第三个return,「选择列表」中没有合适地进行下一步探索,告诉上一层失败
在这里插入图片描述

贪心——455. 分发饼干(简单)

算法小抄没有总结贪心算法,因为贪心没有套路,说白了就是常识性推导和举反例验证。

贪心的本质是选择每一阶段的局部最优,从而达到全局最优。
靠自己手动模拟,如果模拟可行,就可以试一试贪心策略,如果不可行,可能需要动态规划。

之前的田忌赛马也属于贪心,870. 优势洗牌

455题代码

var findContentChildren = function(g, s) {
    g.sort((a, b) => b - a) // 胃口
    s.sort((a, b) => b - a) // 饼干
    let res = 0, index = 0 // 饼干指针
    for(let i=0; i<g.length && index<s.length; i++) {
        if(g[i] <= s[index]) {
            res++
            index++
        }
    }
    return res
};

376. 摆动序列 ()——贪心 或 动规

在这里插入图片描述
在这里插入图片描述
实例2整个序列的差值为(16,-12,5,3,2,-5,11,-8)

我都不知道代码随想录说的是啥。。。看leetcode别人的讲解
在这里插入图片描述
7.因为一段相邻的相同元素中我们最多只能选择其中的一个,所以我们可以忽略相邻的相同元素。
8.对于序列中既非「峰」也非「谷」的元素,我们称其为「过渡元素」。如序列 [1,2,3,4][1,2,3,4] 中,22 和 33 都是「过渡元素」。

贪心算法
了解概念后,好像是在找数学上的极值。然后莫名地变成了大小为3的滑动窗口。

报错案例:
[0,0]
1
报错案例:
【4,2,2,4】如果每次都更新左右差值,会忽略了2这个极小值。所以是双指针,非滑动窗口。
报错案例:
[1,1,1,2,2,2,1,1,1,3,3,3,2,2,2]

如果rightDiff非0,leftDiff 就要取反继承它,因为我是用中间的数减两边。
如果rightDiff为0,就是走向平面,leftDiff保留上一次的坡度。

最后边界情况,防止最后rightDiff一直是0,那么一直没找到极值,那么最右边也被忽略了。方法就是,看leftDiff如果有坡度,则最右边也是极值。
因为最左边肯定算一个,就看最右边。

var wiggleMaxLength = function(nums) {
    if(nums.length == 1) return 1
    let leftDiff = nums[1] - nums[0], rightDiff = 0, res = 0;
    for(let i = 1; i<nums.length - 1; i++) {
        rightDiff = nums[i] - nums[i+1]
        if(leftDiff * rightDiff > 0) {
            res++
        }
        if(rightDiff) leftDiff = -rightDiff
    }
    board = leftDiff ? 2 : 1
    return res + board
};

动态规划算法
动规也不会呀。。。还是要了解山峰和山谷这个概念
在这里插入图片描述
一看解释就觉得很简单,因为动态规划难在:定义数组含义和状态转移方程。
初始化:认为最左边认为是一个极值,可以是极大值也可以是极小值,最右边则不一定。
状态方程:可看到如果与前一个节点值相同,则不处理该节点

var wiggleMaxLength = function(nums) {
    let n = nums.length
    if(n == 1) return 1
    const dp1 = new Array(n).fill(1) // 山峰
    const dp2 = new Array(n).fill(1) // 山谷
    for(let i=1; i<n; i++) {
        for(let j=0; j<i; j++) {
            if(nums[j] > nums[i]) dp2[i] = Math.max(dp2[i], dp1[j]+1)
            if(nums[j] < nums[i]) dp1[i] = Math.max(dp1[i], dp2[j]+1)
        }
    }
    return Math.max(...dp1, ...dp2)
};

保存山峰和山谷的最大值,则dp转移方程中就没有必要j从0遍历到i-1

还是上面好理解,这个简化也是试出来的。或者说明与当前山谷最近的山峰肯定节点更多。
在这里插入图片描述

var wiggleMaxLength = function(nums) {
    let n = nums.length
    if(n == 1) return 1
    let dp1 = 1 // 山峰
    let dp2 = 1 // 山谷
    for(let i=1; i<n; i++) {
        if(nums[i-1] > nums[i]) dp2 = dp1+1
        if(nums[i-1] < nums[i]) dp1 = dp2+1
    }
    return Math.max(dp1, dp2)
};
  数据结构与算法 最新文章
【力扣106】 从中序与后续遍历序列构造二叉
leetcode 322 零钱兑换
哈希的应用:海量数据处理
动态规划|最短Hamilton路径
华为机试_HJ41 称砝码【中等】【menset】【
【C与数据结构】——寒假提高每日练习Day1
基础算法——堆排序
2023王道数据结构线性表--单链表课后习题部
LeetCode 之 反转链表的一部分
【题解】lintcode必刷50题<有效的括号序列
上一篇文章      下一篇文章      查看所有文章
加:2022-03-04 15:50:05  更:2022-03-04 15:53:01 
 
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁

360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年11日历 -2024/11/26 16:32:24-

图片自动播放器
↓图片自动播放器↓
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
图片批量下载器
↓批量下载图片,美女图库↓
  网站联系: qq:121756557 email:121756557@qq.com  IT数码