当前位置:   article > 正文

leetcode刷题记录---19.9.24 路径总和IIIdfs/递归,买卖股票的最佳时机简单,最小栈o1,对称二叉树简单,相交链表,爬楼梯dp三个变量解决_二叉树解决爬楼梯

二叉树解决爬楼梯

1.路经总和III                 没太看懂

题目描述:给定一颗二叉树,和一个整数,要求找出路径中节点和为target的路径种数。

给定一个二叉树,它的每个结点都存放着一个整数值。

找出路径和等于给定数值的路径总数。

路径不需要从根节点开始,也不需要在叶子节点结束,但是路径方向必须是向下的(只能从父节点到子节点)。

二叉树不超过1000个节点,且节点数值范围是 [-1000000,1000000] 的整数。

思路:深度优先遍历!!!套路都是抽出来dfs,选择需要传的参数,在原函数中定义结果,并返回。

1.定义种类数,传入dfs

2.定义dfs函数

                1.根为空,返回res

                 2.把根的值存入res数组。

                 3.定义左子树中的路径 = dfs递归左子树。   定义右子树中的路径 = dfs递归右子树。

                 4.对于左子树中的路径,向res中压入相加后的值,对于右子树中的路径,向res中压入相加后的值

                        对于res中的值,count是否要加一,取决于x是否会等于给定的sum.                                                                                                                                                                                                                                                                                       

递归:

1.根为空,返回0;

2.返回左右子树的递归相加,再加上当前节点的path函数调用

3.path函数,实现找路径,返回路径种数。递归左右,参数为左右子节点和除去这俩节点值的剩下值。                                                   

  1. //dfs 击败%5.13的对手
  2. class Solution {
  3. public:
  4. vector<int> dfs(TreeNode* root, int sum,int& count){
  5. vector<int> temp;
  6. if(!root) return temp;
  7. temp.push_back({root->val});
  8. auto left = dfs(root->left,sum,count);
  9. auto right = dfs(root->right,sum,count);
  10. for(auto x:left) temp.push_back(x+root->val);
  11. for(auto x:right) temp.push_back(x+root->val);
  12. for(auto x:temp) count+= x == sum;
  13. return temp;
  14. }
  15. int pathSum(TreeNode* root, int sum) {
  16. int res = 0;
  17. dfs(root, sum, res);
  18. return res;
  19. }
  20. };
  21. int path(TreeNode* root,int sum){
  22. if(root == nullptr) return 0;
  23. return (root->val == sum)
  24. +path(root->left,sum-root->val)
  25. +path(root->right,sum-root->val);
  26. }
  27. int pathSum(TreeNode* root,int sum){
  28. if(root == nullptr) return 0;
  29. return path(root,sum)
  30. +pathSum(root->left,sum)
  31. +pathSum(root->right,sum);
  32. }

 

2.买卖股票的最佳时机

题目描述:给定一个数组,每个元素分别代表该天股票价格,只买卖一次的情况下,求收益最大!

示例 1:

输入: [7,1,5,3,6,4]
输出: 5
解释: 在第 2 天(股票价格 = 1)的时候买入,在第 5 天(股票价格 = 6)的时候卖出,最大利润 = 6-1 = 5 。
     注意利润不能是 7-1 = 6, 因为卖出价格需要大于买入价格。
示例 2:

输入: [7,6,4,3,1]
输出: 0
解释: 在这种情况下, 没有交易完成, 所以最大利润为 0。

思路:定义diff(i)表示在第i天卖出时,股票最大收益。显然卖出价固定时,买入价越低,利润越大。

也就是说,在扫面到第i个数字时,只要能记住前i-1个数字的最小值,就可以找到最大利润。

1. 参数判断

2. 定义最小为第一个元素,最大利润为第二个元素减去最小。

3.从第三个元素起,遍历,如果第i-1个元素小于最小的,那就更新最小值。

4.定义当前最大利润,与已保存的最大利润相比较,更新!

  1. class Solution {
  2. public:
  3. int maxProfit(vector<int>& prices) {
  4. if(prices.size()<2) return 0;
  5. int min = prices[0];
  6. int maxProfit = prices[1] - min;
  7. maxProfit = max(maxProfit,0);
  8. for(int i = 2;i<prices.size();++i){
  9. if(prices[i-1] <min) min = prices[i-1];
  10. int maxTemp = prices[i] - min;
  11. if(maxProfit<maxTemp) maxProfit = maxTemp;
  12. }
  13. return maxProfit;
  14. }
  15. };

                                           

3.最小栈

题目描述:设计一个栈,支持push,pop,top,min操作,o(1)的时间复杂度!

示例:

MinStack minStack = new MinStack();
minStack.push(-2);
minStack.push(0);
minStack.push(-3);
minStack.getMin();   --> 返回 -3.
minStack.pop();
minStack.top();      --> 返回 0.
minStack.getMin();   --> 返回 -2.

思路:设置一个辅助栈 

           

  1. class MinStack {
  2. public:
  3. /** initialize your data structure here. */
  4. MinStack() {
  5. deque<int> mindata;
  6. deque<int> data;
  7. }
  8. void push(int x) {
  9. data.push_back(x);
  10. if(mindata.size()>0&&mindata.back()<x) mindata.push_back(mindata.back());
  11. else mindata.push_back(x);
  12. }
  13. void pop() {
  14. if(data.size()>0&&mindata.size()>0){
  15. data.pop_back();
  16. mindata.pop_back();
  17. }
  18. }
  19. int top() {
  20. if(data.size()>0) return data.back();
  21. return -1;
  22. }
  23. int getMin() {
  24. if(data.size()>0&&mindata.size()>0){
  25. return mindata.back();
  26. }
  27. return -1;
  28. }
  29. private:
  30. deque<int> mindata;
  31. deque<int> data;
  32. };

       

4.对称二叉树

题目描述:给定一棵二叉树,判断它是不是镜像对称的。                             

例如,二叉树 [1,2,2,3,4,4,3] 是对称的。

    1
   / \
  2   2
 / \ / \
3  4 4  3
但是下面这个 [1,2,2,null,3,null,3] 则不是镜像对称的:

    1
   / \
  2   2
   \   \
   3    3
说明:

如果你可以运用递归和迭代两种方法解决这个问题,会很加分。

思路:中序遍历LDR,而镜像中序遍历RDL,判断这两个序列是否相等!一定要考虑nullptr

1.定义一个函数,传两个一样的root

2.核心中,底层三个判断:两根都为空&&,返回true。。两根有一个为空||,返回false,两根值不相等,返回false。

3.最后递归返回,(第一个左节点,第二个右节点)&&(第一个右节点,第二个左节点);

  1. bool isSymmetric(TreeNode* root) {
  2. return isSymmetriccore(root,root);
  3. }
  4. bool isSymmetriccore(TreeNode* root1,TreeNode* root2){
  5. if(root1 == nullptr && root2 == nullptr) return true;
  6. if(root1 == nullptr || nullptr == root2) return false;
  7. if(root1->val != root2->val) return false;
  8. return isSymmetriccore(root1->left,root2->right)&&isSymmetriccore(root1->right,root2->left);
  9. }

5相交链表

题目描述:给定两个链表,找出两个链表相交的第一个节点

如下面的两个链表:

在节点 c1 开始相交。

 

示例 1:

输入:intersectVal = 8, listA = [4,1,8,4,5], listB = [5,0,1,8,4,5], skipA = 2, skipB = 3
输出:Reference of the node with value = 8
输入解释:相交节点的值为 8 (注意,如果两个列表相交则不能为 0)。从各自的表头开始算起,链表 A 为 [4,1,8,4,5],链表 B 为 [5,0,1,8,4,5]。在 A 中,相交节点前有 2 个节点;在 B 中,相交节点前有 3 个节点。
 

示例 2:

输入:intersectVal = 2, listA = [0,9,1,2,4], listB = [3,2,4], skipA = 3, skipB = 1
输出:Reference of the node with value = 2
输入解释:相交节点的值为 2 (注意,如果两个列表相交则不能为 0)。从各自的表头开始算起,链表 A 为 [0,9,1,2,4],链表 B 为 [3,2,4]。在 A 中,相交节点前有 3 个节点;在 B 中,相交节点前有 1 个节点。
 

示例 3:

输入:intersectVal = 0, listA = [2,6,4], listB = [1,5], skipA = 3, skipB = 2
输出:null
输入解释:从各自的表头开始算起,链表 A 为 [2,6,4],链表 B 为 [1,5]。由于这两个链表不相交,所以 intersectVal 必须为 0,而 skipA 和 skipB 可以是任意值。
解释:这两个链表不相交,因此返回 null。
 

注意:

如果两个链表没有交点,返回 null.
在返回结果后,两个链表仍须保持原有的结构。
可假定整个链表结构中没有循环。
程序尽量满足 O(n) 时间复杂度,且仅用 O(1) 内存。

思路:剑指offer面试题52

1.先得到两个链表的长度

2.再长链表上先走出多的部分

3.只要(长不为空&&短不为空&&长不等于短),那么长短同时后移。

4.得到第一个公共节点

  1. /**
  2. * Definition for singly-linked list.
  3. * struct ListNode {
  4. * int val;
  5. * ListNode *next;
  6. * ListNode(int x) : val(x), next(NULL) {}
  7. * };
  8. */
  9. class Solution {
  10. public:
  11. ListNode *getIntersectionNode(ListNode *headA, ListNode *headB) {
  12. int sizeA = 0;
  13. int sizeB = 0;
  14. ListNode* p = headA;
  15. ListNode* q = headB;
  16. while(p != nullptr){sizeA++;p = p->next;} p = headA;
  17. while(q != nullptr){sizeB++;q = q->next;} q = headB;
  18. if(sizeA>sizeB){
  19. int k = sizeA-sizeB;
  20. while(k--&&p!=nullptr) p = p->next;
  21. while((p!=nullptr)&&(q!=nullptr)&&(p!=q)){p = p->next;q= q->next;}
  22. }
  23. else{
  24. int k = sizeB-sizeA;
  25. while(k--&&q!=nullptr) {q = q->next;}
  26. while((p!=nullptr)&&(q!=nullptr)&&(p!=q)){p = p->next;q= q->next;}
  27. }
  28. ListNode* temp = p;
  29. if(temp==nullptr) return nullptr;
  30. else return temp;
  31. }
  32. };

                                                       

6.爬楼梯

题目描述:假设正在爬楼梯,共n阶,每次可以爬1或者2个台阶,试问共有多少种方法爬到楼顶?

示例 1:

输入: 2
输出: 2
解释: 有两种方法可以爬到楼顶。
1.  1 阶 + 1 阶
2.  2 阶
示例 2:

输入: 3
输出: 3
解释: 有三种方法可以爬到楼顶。
1.  1 阶 + 1 阶 + 1 阶
2.  1 阶 + 2 阶
3.  2 阶 + 1 阶

思路:剑指offer上原题,动态规划dp[i] = dp[i-1]+dp[i-2]

1.三个变量解决

  1. class Solution {
  2. public:
  3. int climbStairs(int n) {
  4. if(n==1) return 1;
  5. if(n ==2) return 2;
  6. int a = 1;
  7. int b = 2;
  8. int c = a+b;
  9. while(n-2>0){
  10. c = a+b;
  11. a = b;
  12. b = c;
  13. n--;
  14. }
  15. return c;
  16. }
  17. };

                                                                                                                                      

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/秋刀鱼在做梦/article/detail/788798
推荐阅读
相关标签
  

闽ICP备14008679号