LeetCode刷题C++

Posted 猫头丁

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了LeetCode刷题C++相关的知识,希望对你有一定的参考价值。

5.最长回文字符串

给你一个字符串 s,找到 s 中最长的回文子串。
划定步长,遍历判断

class Solution 
public:
    string longestPalindrome(string s) 
        if(s.size() < 2)
            return s;
        
        int maxlen = 1;
        int begin = 0;
        int dp[s.size()][s.size()];
        for(int i  = 0 ; i < s.size() ; i++)
            dp[i][i] = 1;
        
        for(int l = 2 ; l <= s.size() ; l++)
            for(int i = 0 ; i < s.size() ; i++)
                int j = l + i - 1;
                if(j >= s.size())
                    break;
                
                if(s[i] != s[j])
                    dp[i][j] = 0;
                
                else
                    if(j-i < 3)
                        dp[i][j] = 1;
                    
                    else
                        dp[i][j] = dp[i+1][j-1];
                    
                
                if(dp[i][j]>0 && j-i+1 > maxlen)
                    maxlen = j - i + 1;
                    begin = i;
                
            
        
        return s.substr(begin, maxlen);

    
;

20.有效的括号

给定一个只包括 ‘(’,’)’,’’,’’,’[’,’]’ 的字符串 s ,判断字符串是否有效。

有效字符串需满足:

左括号必须用相同类型的右括号闭合。
左括号必须以正确的顺序闭合。
class Solution 
public:
    bool isValid(string s) 
        int n = s.size();
        if(n % 2 == 1)
            return false;
        
        unordered_map<char,char> pairs = 
            ')','(',
            ']','[',
            '','',
        ;
        stack<char> stk;
        for(char ch:s)
            if(pairs.count(ch))
                if(stk.empty() || stk.top() != pairs[ch])
                    return false;
                
                stk.pop();
            
            else
                stk.push(ch);
            
        
        return stk.empty();
    
;

45.跳跃游戏

给你一个非负整数数组 nums ,你最初位于数组的第一个位置
数组中的每个元素代表你在该位置可以跳跃的最大长度。
你的目标是使用最少的跳跃次数到达数组的最后一个位置。
假设你总是可以到达数组的最后一个位置。
可以理解为背包问题

class Solution 
public:
    int jump(vector<int>& nums) 
        int n = nums.size();
        int dp[n];
        for(int i = 0 ; i < n ; i++)
            dp[i] = 10000;
        
        dp[0] = 0;
        for(int i = 0 ; i < n - 1 ; i++)
            for(int j = 1 ; j <= nums[i] ; j++)
                if(i + j >= n)
                    break;
                
                dp[i+j] = min(dp[i+j], dp[i]+1); 
            
        
        return dp[n-1];
    
;

66.加一

给定一个由 整数 组成的 非空 数组所表示的非负整数,在该数的基础上加一。

最高位数字存放在数组的首位, 数组中每个元素只存储单个数字。

你可以假设除了整数 0 之外,这个整数不会以零开头。

class Solution 
public:
    vector<int> plusOne(vector<int>& digits) 
        int n = digits.size() - 1;
        if(digits[n] != 9)
            digits[n] = digits[n] + 1;
        
        else
            while(n >= 0 && digits[n] == 9)
                digits[n] = 0;
                n--;
            
            if(n >= 0)
                digits[n]++;
            
            else
                digits.insert(digits.begin(),1);
            
        
        return digits;
    
;

72.编辑距离

给你两个单词 word1 和 word2, 请返回将 word1 转换成 word2 所使用的最少操作数 。

你可以对一个单词进行如下三种操作:

插入一个字符
删除一个字符
替换一个字符


class Solution 
public:
    int minDistance(string word1, string word2) 
        int n = word1.length();
        int m = word2.length();
        // 有一个字符串为空串
        if(n * m == 0)
            return n + m;
        
        // DP数组
        vector<vector<int>> D(n+1, vector<int>(m+1));
        // 边界状态初始化
        for(int i = 0 ; i < n + 1 ; i++)
            D[i][0] = i;
        
        for(int j = 0 ; j < m + 1 ; j++)
            D[0][j] = j;
        
        // 计算所有dp值
        for(int i = 1 ; i < n + 1 ; i++)
            for(int j = 1 ; j < m + 1 ; j++)
                int left = D[i-1][j] + 1;
                int down = D[i][j-1] + 1;
                int left_down = D[i-1][j-1];
                if(word1[i-1] != word2[j-1])
                    left_down++;
                
                D[i][j] = min(left, min(down, left_down));
            
        
        return D[n][m];
    
;

88.合并两个有序数组

给你两个按 非递减顺序 排列的整数数组 nums1 和 nums2,另有两个整数 m 和 n ,分别表示 nums1 和 nums2 中的元素数目。

请你 合并 nums2 到 nums1 中,使合并后的数组同样按 非递减顺序 排列。

注意:最终,合并后数组不应由函数返回,而是存储在数组 nums1 中。为了应对这种情况,nums1 的初始长度为 m + n,其中前 m 个元素表示应合并的元素,后 n 个元素为 0 ,应忽略。nums2 的长度为 n 。

class Solution 
public:
    void merge(vector<int>& nums1, int m, vector<int>& nums2, int n) 
        vector<int> nums3 = nums1;
        int s = 0;
        int t = 0;
        for(int i = 0 ; i < m + n ; i++)
            if(s == m)
                nums1[i] = nums2[t];
                t++;
            
            else if(t == n)
                nums1[i] = nums3[s];
                s++;
            
            else if(nums3[s] < nums2[t])
                nums1[i] = nums3[s];
                s++;
            
            else
                nums1[i] = nums2[t];
                t++;
            
        
    
;

91.解码方法

一条包含字母 A-Z 的消息通过以下映射进行了 编码 :
‘A’ -> “1”
‘B’ -> “2”

‘Z’ -> “26”
要 解码 已编码的消息,所有数字必须基于上述映射的方法,反向映射回字母(可能有多种方法)。例如,“11106” 可以映射为:

"AAJF" ,将消息分组为 (1 1 10 6)
"KJF" ,将消息分组为 (11 10 6)

注意,消息不能分组为 (1 11 06) ,因为 “06” 不能映射为 “F” ,这是由于 “6” 和 “06” 在映射中并不等价。

给你一个只含数字的 非空 字符串 s ,请计算并返回 解码 方法的 总数 。
动态规划,注意各种判断条件

class Solution 
public:
    int numDecodings(string s) 
        int n = s.size();
        if(s[0] == '0')
            return 0;
        
        if(n < 2)
            return n;
        
        int dp[n+1];
        dp[0] = 1;
        dp[1] = 1;
        for(int i = 2 ; i <= n ; i++)
            int temp = (s[i-2] - '0') * 10 + s[i-1] - '0';
            if(temp <= 26 && temp > 10 && temp != 20)
                dp[i] = dp[i-1] + dp[i-2];
            
            else if(temp > 26 && s[i-1]=='0')
                return 0;
            
            else if((temp < 10 && temp > 0) || temp > 26)
                dp[i] = dp[i-1];
            
            else if(temp == 10 || temp == 20)
                dp[i] = dp[i-2];
            
            else if(temp == 0)
                return 0;
            
        
        return dp[n];
    
;

94.二叉树的中序遍历

给定一个二叉树的根节点 root ,返回它的 中序 遍历。

/**
 * 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:
    vector<int> inorderTraversal(TreeNode* root) 
        vector<int> mid;
        stack<TreeNode*> s;
        while(root != nullptr || !s.empty())
            while(root != nullptr)
                s.push(root);
                root = root->left;
            
            root = s.top();
            s.pop();
            mid.push_back(root->val);
            root = root->right;
        
        return mid;
    
;

95.不同的二叉搜索树

给你一个整数 n ,请你生成并返回所有由 n 个节点组成且节点值从 1 到 n 互不相同的不同 二叉搜索树 。可以按 任意顺序 返回答案。
好难,多看几次,试着理解吧。

class Solution 
public:
    vector<TreeNode*> generateTrees(int start, int end) 
        if (start > end) 
            return  nullptr ;
        
        vector<TreeNode*> allTrees;
        // 枚举可行根节点
        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);
                
            
        
        return allTrees;
    
    vector<TreeNode*> generateTrees(int n) 
        if (!n) 
            return ;
        
        return generateTrees(1, n);
    
;

97.交错字符串

给定三个字符串 s1、s2、s3,请你帮忙验证 s3 是否是由 s1 和 s2 交错 组成的。

两个字符串 s 和 t 交错 的定义与过程如下,其中每个字符串都会被分割成若干 非空 子字符串:

s = s1 + s2 + ... + sn
t = t1 + t2 + ... + tm
|n - m| <= 1
交错 是 s1 + t1 + s2 + t2 + s3 + t3 + ... 或者 t1 + s1 + t2 + s2 + t3 + s3 + ...

注意:a + b 意味着字符串 a 和 b 连接。
这道题用双指针,结果会出现错误,因此使用动态规划,考虑s1的前i个字符能否和s2的前j个字符一起组成s3的前i+j个字符

class Solution 
public:
    bool isInterleave(string s1, string s2, string s3) 
        if(s1.size() + s2.size() != s3.size())
            return false;
        
       int dp[s1.size()+1][s2.size()+1];
        for(int i = 0 ; i <= s1.size() ; i++)
            for(int j = 0 ; j <= s2.size() ; j++)
                    dp[i][j] = 0;
            
        
        dp[0][0] = 1;
        for(int i = 1 ; i <=<

以上是关于LeetCode刷题C++的主要内容,如果未能解决你的问题,请参考以下文章

LeetCode刷题模版:231 - 240

leetcode-236-二叉树公共祖先

LeetCode Java刷题笔记—236. 二叉树的最近公共祖先

Leetcode刷题Python236. 二叉树的最近公共祖先

LeetCode刷题笔记-数据结构-day18

LeetCode刷题笔记-数据结构-day18