算法学习

title:  算法学习
author: zsw

 

 

 

 

算法学习动态规划剑指offer47 礼物的最大价值https://leetcode-cn.com/problems/li-wu-de-zui-da-jie-zhi-lcof/solution/mian-shi-ti-47-li-wu-de-zui-da-jie-zhi-dong-tai-gu/卡特兰数 打家劫舍 1—3打家劫舍1打家劫舍2打家劫舍3找数字规律剑指43 1~n整数中1出现的次数剑指44 数字序列中某一位的数字剑指45. 把数组排成最小的数(自定义排序)二分查找

 

算法学习

动态规划

剑指offer47 礼物的最大价值

在一个 m*n 的棋盘的每一格都放有一个礼物,每个礼物都有一定的价值(价值大于 0)。你可以从棋盘的左上角开始拿格子里的礼物,并每次向右或者向下移动一格、直到到达棋盘的右下角。给定一个棋盘及其上面的礼物的价值,请计算你最多能拿到多少价值的礼物?

https://leetcode-cn.com/problems/li-wu-de-zui-da-jie-zhi-lcof/solution/mian-shi-ti-47-li-wu-de-zui-da-jie-zhi-dong-tai-gu/

image-20200722114530094

 

不同的二叉搜索树1

卡特兰数

假设n个节点存在二叉排序树的个数是G(n),令f(i)为以i为根的二叉搜索树的个数,则 G(n) = f(1) + f(2) + f(3) + f(4) + ... + f(n)G(n)=f(1)+f(2)+f(3)+f(4)+...+f(n)

当i为根节点时,其左子树节点个数为i-1个,右子树节点为n-i,则 f(i) = G(i-1)*G(n-i)f(i)=G(i−1)∗G(n−i)

综合两个公式可以得到 卡特兰数 公式 G(n) = G(0)G(n-1)+G(1)G(n-2)+...+G(n-1)*G(0)G(n)=G(0)∗G(n−1)+G(1)∗(n−2)+...+G(n−1)∗G(0)

打家劫舍 1—3

打家劫舍1

你是一个专业的小偷,计划偷窃沿街的房屋。每间房内都藏有一定的现金,影响你偷窃的唯一制约因素就是相邻的房屋装有相互连通的防盗系统,如果两间相邻的房屋在同一晚上被小偷闯入,系统会自动报警。给定一个代表每个房屋存放金额的非负整数数组,计算你 不触动警报装置的情况下 ,一夜之内能够偷窃到的最高金额。

dp 方程 dp[i] = max(dp[i-2]+nums[i], dp[i-1])

    int rob(vector<int>& nums) {
        if (nums.empty()) {
            return 0;
        }
        int size = nums.size();
        if (size == 1) {
            return nums[0];
        }
        vector<int> dp = vector<int>(size, 0);
        dp[0] = nums[0];
        dp[1] = max(nums[0], nums[1]);
        for (int i = 2; i < size; i++) {
            dp[i] = max(dp[i - 2] + nums[i], dp[i - 1]);
        }
        return dp[size - 1];
    }

打家劫舍2

你是一个专业的小偷,计划偷窃沿街的房屋,每间房内都藏有一定的现金。这个地方所有的房屋都围成一圈,这意味着第一个房屋和最后一个房屋是紧挨着的。同时,相邻的房屋装有相互连通的防盗系统,如果两间相邻的房屋在同一晚上被小偷闯入,系统会自动报警。

把环拆成两个队列,一个是从0到n-1,另一个是从1到n,然后返回两个结果最大的。

 int rob(vector<int>& nums) {
        if(nums.size()==0) return 0;
        if(nums.size()==1) return nums[0];
​
        vector<int> dp1(nums.size());
        vector<int> dp2(nums.size());
        dp1[0] = nums[0];  //dp1偷第一间  dp2不偷第一间
        dp1[1] = max(nums[1],dp1[0]);
        
        dp2[0] = 0;
        dp2[1] = nums[1];
​
        for(int i=2;i<nums.size();++i)
        {
            dp1[i] = max(dp1[i-1],nums[i]+dp1[i-2]);
            dp2[i] = max(dp2[i-1],nums[i]+dp2[i-2]);
        }
       
        return max(dp1[nums.size()-2],dp2[nums.size()-1]);
    }

打家劫舍3

在上次打劫完一条街道之后和一圈房屋后,小偷又发现了一个新的可行窃的地区。这个地区只有一个入口,我们称之为“根”。 除了“根”之外,每栋房子有且只有一个“父“房子与之相连。一番侦察之后,聪明的小偷意识到“这个地方的所有房屋的排列类似于一棵二叉树”。 如果两个直接相连的房子在同一天晚上被打劫,房屋将自动报警。

  • 对于一个以 node 为根节点的二叉树而言,如果尝试偷取 node 节点,那么势必不能偷取其左右子节点,然后继续尝试偷取其左右子节点的左右子节点。

  • 如果不偷取该节点,那么只能尝试偷取其左右子节点。

  • 比较两种方式的结果,谁大取谁。

class Solution {
    unordered_map<TreeNode *,int> sums;
public:
    int rob(TreeNode* root) {
     return tryrob(root);
    }
    int tryrob(TreeNode *root)
    {
        if(!root) return 0;
        if(sums.count(root)) return sums[root];
        int res1 = 0;
        //偷取当前节点,就只能偷取当前节点的子节点的子节点。
        if(root->left)
        {
            res1+=tryrob(root->left->left)+tryrob(root->left->right);
        }
        if(root->right)
        {
            res1+=tryrob(root->right->left)+tryrob(root->right->right);
        }
        res1+=root->val;
​
        //不偷取当前节点  就只能偷取当前节点的子节点
        int res2=0;
        res2 = tryrob(root->left)+tryrob(root->right);
        sums[root] = max(res1,res2);
        return max(res1,res2);
    }
};

不同的二叉搜索树2

递归

    for (int i = start; i <= end; i++) {
        // 获得所有可行的左子树集合
        vector<TreeNode*> leftTrees = generateTrees(start, i - 1);
​
        // 获得所有可行的右子树集合
        vector<TreeNode*> rightTrees = generateTrees(i + 1, end);
​
        // 从左子树集合中选出一棵左子树,从右子树集合中选出一棵右子树,拼接到根节点上
        for (auto& left : leftTrees) {
            for (auto& right : rightTrees) {
                TreeNode* currTree = new TreeNode(i);
                currTree->left = left;
                currTree->right = right;
                allTrees.emplace_back(currTree);
            }
        }
    }

找数字规律

剑指43 1~n整数中1出现的次数

输入一个整数 n ,求1~n这n个整数的十进制表示中1出现的次数。

image-20200721124257385

image-20200721124239937

image-20200721124310369

剑指44 数字序列中某一位的数字

数字以0123456789101112131415…的格式序列化到一个字符序列中。在这个序列中,第5位(从下标0开始计数)是5,第13位是1,第19位是4,等等。

请写一个函数,求任意第n位对应的数字。

image-20200721123906064

 

剑指45. 把数组排成最小的数(自定义排序)

输入一个非负整数数组,把数组里所有数字拼接起来排成一个数,打印能拼接出的所有数字中最小的一个。

image-20200721133821377

二分查找

剑指offer11 旋转数组的最小值

把一个数组最开始的若干个元素搬到数组的末尾,我们称之为数组的旋转。输入一个递增排序的数组的一个旋转,输出旋转数组的最小元素。例如,数组 [3,4,5,1,2] 为 [1,2,3,4,5] 的一个旋转,该数组的最小值为1。

https://leetcode-cn.com/problems/xuan-zhuan-shu-zu-de-zui-xiao-shu-zi-lcof/solution/mian-shi-ti-11-xuan-zhuan-shu-zu-de-zui-xiao-shu-3/

image-20200722110440553

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
Python算法学习是指掌握使用Python语言来解决各种问题的方法和技巧。在学习过程中,有几个重要的方面需要注意。 首先,了解基本的算法概念是必不可少的。例如,了解常见的排序算法(如冒泡排序、快速排序)和查找算法(如二分查找)等。这有助于我们理解算法的原理和思想。 其次,学习Python中的内置数据结构和函数,如列表、字典和字符串等。熟悉这些数据结构和函数的使用方法,可以帮助我们更好地解决问题,并编写出高效的算法。 第三,了解常用的算法设计技巧。例如,贪心算法、动态规划和分治法等。这些算法设计技巧可以应用于不同类型的问题,帮助我们找到解决问题的最佳方法。 第四,编写和调试算法代码是学习过程中的关键步骤。我们可以通过编写小型的算法程序来练习和巩固所学的知识。同时,调试是解决代码错误和优化算法的重要环节,需要耐心和细心。 最后,不断练习和实践是提高算法能力的关键。我们可以通过刷题、参加编程比赛和项目实践等方式来提高自己的算法水平。与其他程序员交流和分享经验也是相互学习的好机会。 总之,Python算法学习是一个渐进的过程,需要不断学习、实践和提高。通过合理的学习方法和坚持不懈的努力,我们可以不断提高自己的算法能力,并运用它来解决实际问题。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值