leetcode剑指 Offer 专项突击版(051、008、016)

简介: leetcode剑指 Offer 专项突击版(051、008、016)

剑指 Offer II 051. 节点之和最大的路径


题目描述:

路径 被定义为一条从树中任意节点出发,沿父节点-子节点连接,达到任意节点的序列。同一个节点在一条路径序列中 至多出现一次 。该路径 至少包含一个 节点,且不一定经过根节点。


路径和 是路径中各节点值的总和。


给定一个二叉树的根节点 root ,返回其 最大路径和,即所有路径上节点值之和的最大值。

示例:

02f0ee547d504e7097360a031e8e2996.png

思路:

这个路径,可以是左子结点 根结点 右子结点。可以不包括root结点!!

不是简单的走完所有的路,求和!

要判断左右子树结点和是否有利于和最大,所以比较这是不是一个比0大的,起正向作用的。

注意,返回值是什么,走到空指针的时候,返回值应该是0,而不是max_num。以及走完一条路,返回的是根节点加左右子树中大的路径和。


代码:

一开始思路错误,求的所有的和,想改前缀和也不对。

/**
 * Definition for a binary tree node.
 * struct TreeNode {
 *     int val;
 *     TreeNode *left;
 *     TreeNode *right;
 *     TreeNode() : val(0), left(nullptr), right(nullptr) {}
 *     TreeNode(int x) : val(x), left(nullptr), right(nullptr) {}
 *     TreeNode(int x, TreeNode *left, TreeNode *right) : val(x), left(left), right(right) {}
 * };
 */
class Solution {
public:
    int dfs(TreeNode* root,int& max_num){
        if(root == nullptr)
            return 0;
        int left = max(0,dfs(root->left,max_num));
        int right = max(0,dfs(root->right,max_num));
        max_num = max(root->val + left + right,max_num);
        return root->val + max(left,right);
    }
    int maxPathSum(TreeNode* root) {
        int max_num = INT_MIN;
        dfs(root,max_num);
        return max_num;
    }
    // int dfs(TreeNode* root,int sums,int max_num)
    // {
    //     i++;
    //     if(root == nullptr)
    //     {
    //         // printf("%d ",sum);
    //         return sum;
    //     }
    //     sum = dfs(root->left,sum,max_num);
    //     sum = dfs(root->right,sum,max_num);
    //     // if(root->left == nullptr && root->right == nullptr)
    //     // {
    //     sum[i] += root->val;
    //     // if()
    //     max_num = max(max_num,sum);
    //     // }
    //     printf("%d",max_num);
    //     return sum;
    // }
    // int maxPathSum(TreeNode* root) {
    //     // int vector<int> sums;
    //     int sum = 0;
    //     int max_num = 0;
    //     // sums[0] = 0;
    //     return dfs(root,sum,max_num);
    // }
};


剑指 Offer II 008. 和大于等于 target 的最短子数组


题目描述:

给定一个含有 n 个正整数的数组和一个正整数 target 。


找出该数组中满足其和 ≥ target 的长度最小的 连续子数组 [numsl, numsl+1, …, numsr-1, numsr] ,并返回其长度。如果不存在符合条件的子数组,返回 0 。


示例:

08db012fb37a4af6997a82389a8b14ea.png


思路:

直接滑动窗口,o(n)复杂度。

应该优化用前缀和加二分查找。


代码:

滑动窗口:

class Solution {
public:
    int minSubArrayLen(int target, vector<int>& nums) {
        int min_size = 99999999;
        int len = nums.size();
        int right = 0;
        int left = 0;
        long long sum = 0;
        while(right < len)
        {
            sum += nums[right];
            while(sum >= target)
            {
                min_size = min(min_size,right-left+1);
                // sum += nums[right];
                sum -= nums[left];
                left++;
            }
            right++;
        }
        return min_size < 99999999 ? min_size : 0;
    }
};

前缀和+二分

class Solution {
public:
    int bin_search(vector<int>& nums, int s, int e, int tar) {
        int l = s, r = e;
        while (l < r) {
            int mid = (l + r) >> 1;
            if (nums[mid] >= tar) {
                r = mid;
            } else {
                l = mid + 1;
            }
        }
        if (nums[r] < tar) return -1;
        return r;
    }
    int minSubArrayLen(int target, vector<int>& nums) {
        for (int i = 1; i < nums.size(); ++i) {
            nums[i] += nums[i - 1];
        }
        int sd = 0;
        int ans = INT_MAX;
        for (int i = 0; i < nums.size(); ++i) {
            // 需要在后续前缀和数组中搜索的值
            if (i == 0) {
                sd = target;
            } else {
                sd = nums[i - 1] + target;
            }
            // 寻找第一个大于等于 sd 的值的位置
            int idx = bin_search(nums, i, nums.size() - 1, sd);
            if (idx < 0) {
                break;
            } else {
                ans = min(ans, idx - i + 1);
            }
        }
        return ans == INT_MAX ? 0 : ans;
    }
};


剑指 Offer II 016. 不含重复字符的最长子字符串


题目描述:

给定一个字符串 s ,请你找出其中不含有重复字符的 最长连续子字符串 的长度。

思路:

直接滑动窗口+set

代码:

// #include <algorithm>
class Solution {
public:
    int lengthOfLongestSubstring(string s) {
        int n = s.length();
        if(n == 1) return 1;
        if(n == 0) return 0;
        set<char> window;
        int max_size = 1;
        //这是一个窗口
        int right = 0,left = 0;
        while(right < n)
        {
            if(window.count(s[right]))
            {
                window.erase(s[left]);
                left++;
            }
            else
            {
                window.insert(s[right]);
                max_size = max(int(window.size()),max_size);
                right++;
            }
        }
        return max_size;
    }
};
相关文章
|
2月前
|
存储
【LeetCode】剑指 Offer 54. 二叉搜索树的第k大节点
【LeetCode】剑指 Offer 54. 二叉搜索树的第k大节点
25 1
|
2月前
|
算法 DataX
二叉树(中)+Leetcode每日一题——“数据结构与算法”“剑指Offer55-I. 二叉树的深度”“100.相同的树”“965.单值二叉树”
二叉树(中)+Leetcode每日一题——“数据结构与算法”“剑指Offer55-I. 二叉树的深度”“100.相同的树”“965.单值二叉树”
|
2月前
|
算法 定位技术
【leetcode】剑指 Offer II 105. 岛屿的最大面积-【深度优先DFS】
【leetcode】剑指 Offer II 105. 岛屿的最大面积-【深度优先DFS】
24 0
|
2月前
|
Go
golang力扣leetcode 剑指Offer II 114. 外星文字典
golang力扣leetcode 剑指Offer II 114. 外星文字典
31 0
|
2月前
「LeetCode」剑指 Offer 40. 最小的k个数
「LeetCode」剑指 Offer 40. 最小的k个数
35 0
|
2月前
leetcode 剑指 Offer 32 - III. 从上到下打印二叉树 III
leetcode 剑指 Offer 32 - III. 从上到下打印二叉树 III
28 0
|
2月前
leetcode 剑指 Offer 32 - II. 从上到下打印二叉树 II
leetcode 剑指 Offer 32 - II. 从上到下打印二叉树 II
31 0
|
2月前
/leetcode 剑指 Offer 32 - I. 从上到下打印二叉树
/leetcode 剑指 Offer 32 - I. 从上到下打印二叉树
26 0
|
16天前
|
算法 C++
【数据结构与算法】:关于时间复杂度与空间复杂度的计算(C/C++篇)——含Leetcode刷题-2
【数据结构与算法】:关于时间复杂度与空间复杂度的计算(C/C++篇)——含Leetcode刷题
|
16天前
|
算法 C++
【数据结构与算法】:关于时间复杂度与空间复杂度的计算(C/C++篇)——含Leetcode刷题-1
【数据结构与算法】:关于时间复杂度与空间复杂度的计算(C/C++篇)——含Leetcode刷题