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函数,实现找路径,返回路径种数。递归左右,参数为左右子节点和除去这俩节点值的剩下值。                                                   

//dfs   击败%5.13的对手
class Solution {
public:
    vector<int> dfs(TreeNode* root, int sum,int& count){
        vector<int> temp;
        if(!root) return temp;
        temp.push_back({root->val});
        auto left = dfs(root->left,sum,count);
        auto right = dfs(root->right,sum,count);
        for(auto x:left) temp.push_back(x+root->val);
        for(auto x:right) temp.push_back(x+root->val);
        for(auto x:temp) count+= x == sum;
        return temp;
    }  
    int pathSum(TreeNode* root, int sum) {
        int res = 0;
        dfs(root, sum, res);
        return res;
    }
};





int path(TreeNode* root,int sum){
        if(root == nullptr) return 0;
        return (root->val == sum)
            +path(root->left,sum-root->val)
            +path(root->right,sum-root->val);
    }
    int pathSum(TreeNode* root,int sum){
        if(root == nullptr) return 0;
        return path(root,sum)
            +pathSum(root->left,sum)
            +pathSum(root->right,sum);
    }

 

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.定义当前最大利润,与已保存的最大利润相比较,更新!

class Solution {
public:
    int maxProfit(vector<int>& prices) {
        if(prices.size()<2) return 0;
        int min = prices[0];
        int maxProfit = prices[1] - min;
        maxProfit = max(maxProfit,0);
        for(int i = 2;i<prices.size();++i){
            if(prices[i-1] <min) min = prices[i-1];
            int maxTemp = prices[i] - min;
            if(maxProfit<maxTemp) maxProfit = maxTemp;
        }
        return maxProfit;
    }
};

                                           

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.

思路:设置一个辅助栈 

           

class MinStack {
public:
    /** initialize your data structure here. */
    MinStack() {
        deque<int> mindata;
        deque<int> data;
    }
    
    void push(int x) {
        data.push_back(x);
        if(mindata.size()>0&&mindata.back()<x) mindata.push_back(mindata.back());
        else mindata.push_back(x);
    }
    
    void pop() {
        if(data.size()>0&&mindata.size()>0){
            data.pop_back();
            mindata.pop_back();
        }
    }
    
    int top() {
        if(data.size()>0) return data.back();
        return -1;
    }
    
    int getMin() {
        if(data.size()>0&&mindata.size()>0){
            return mindata.back();
        }
        return -1;
    }
private:
    deque<int> mindata;
    deque<int> data;
};

       

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.最后递归返回,(第一个左节点,第二个右节点)&&(第一个右节点,第二个左节点);

bool isSymmetric(TreeNode* root) {
        return isSymmetriccore(root,root);
    }
    bool isSymmetriccore(TreeNode* root1,TreeNode* root2){
        if(root1 == nullptr && root2 == nullptr) return true;
        if(root1 == nullptr || nullptr == root2) return false;
        if(root1->val != root2->val) return false;
        return isSymmetriccore(root1->left,root2->right)&&isSymmetriccore(root1->right,root2->left);
        
    }
    

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.得到第一个公共节点

/**
 * Definition for singly-linked list.
 * struct ListNode {
 *     int val;
 *     ListNode *next;
 *     ListNode(int x) : val(x), next(NULL) {}
 * };
 */
class Solution {
public:
    ListNode *getIntersectionNode(ListNode *headA, ListNode *headB) {
        int sizeA = 0;
        int sizeB = 0;
        ListNode* p = headA;
        ListNode* q = headB;
        while(p != nullptr){sizeA++;p = p->next;} p = headA;
        while(q != nullptr){sizeB++;q = q->next;} q = headB;
        if(sizeA>sizeB){
            int k = sizeA-sizeB;
            while(k--&&p!=nullptr) p = p->next;
            while((p!=nullptr)&&(q!=nullptr)&&(p!=q)){p = p->next;q= q->next;}
        }
        else{
            int k = sizeB-sizeA;
            while(k--&&q!=nullptr) {q = q->next;}
            while((p!=nullptr)&&(q!=nullptr)&&(p!=q)){p = p->next;q= q->next;}
        }
        ListNode* temp = p;
        if(temp==nullptr) return nullptr;
        else return temp;
    }
};

                                                       

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.三个变量解决

class Solution {
public:
    int climbStairs(int n) {
        if(n==1) return 1;
        if(n ==2) return 2;
        int a = 1;
        int b = 2;
        int c = a+b;
        while(n-2>0){
            c = a+b;
            a = b;
            b = c;
            n--;
        }
        return c;
    }
};

                                                                                                                                      

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值