分类 LeetCode 下的文章

盛最多水的容器

问题描述

给定 n 个非负整数 a1,a2,...,an,每个数代表坐标中的一个点 (i, ai) 。在坐标内画 n 条垂直线,垂直线 i 的两个端点分别为 (i, ai) 和 (i, 0)。找出其中的两条线,使得它们与 x 轴共同构成的容器可以容纳最多的水。
说明:你不能倾斜容器,且 n 的值至少为 2。
question_11 (1).jpg
图中垂直线代表输入数组 [1,8,6,2,5,4,8,3,7]。在此情况下,容器能够容纳水(表示为蓝色部分)的最大值为 49。

示例:
输入: [1,8,6,2,5,4,8,3,7]
输出: 49

来源:力扣(LeetCode)
链接:https://leetcode-cn.com/problems/container-with-most-water

思路

容器容纳水的多少,取决于两个方面--两个直线间的距离以及两个直线中比较短的那个高度
本题的思想是双指针:
first=0;last=n-1;因为取决于比较短的那个高度,所以,每次短的那个指针向高的方向移动,来寻求高度的最大值。在这个过程中,直线之间的长度会变小,所以,这就需要在这个高度不断增大,长度不断较小的过程中寻求一个最大的值。

题解

class Solution {
public:
    int maxArea(vector<int>& height) {
        int n=height.size();
        int first=0;
        int last=n-1;
        int smax=0;
      
        while (first<last){
            int sa=min(height[first],height[last])*(last-first);
            if(s>smax){
                smax=s;
            }
            if(height[first]<height[last]){
                first++;
            }
            else if(height[first]>height[last])
            {
                last--;
            } else{
                first++;
            }
        }
        return smax;
    }
};

电话号码的字母组合

问题描述

给定一个仅包含数字 2-9 的字符串,返回所有它能表示的字母组合。
给出数字到字母的映射如下(与电话按键相同)。注意 1 不对应任何字母。

17_telephone_keypad.png

示例:
输入:"23"
输出:["ad", "ae", "af", "bd", "be", "bf", "cd", "ce", "cf"].
说明:
尽管上面的答案是按字典序排列的,但是你可以任意选择答案输出的顺序。

来源:力扣(LeetCode)
链接:https://leetcode-cn.com/problems/letter-combinations-of-a-phone-number

思路

首先在电话号码的数字和字母之间进行一个映射, map<char, string> table;
vector ret作为最后返回的结果,cur作为中间暂存结果,当递归次数index等于digits.length()时,将cur存入到ret中
当index小于digits.length()时,

for(int i=0;i<table[digits[index]].length();i++){
            dfs(digits,cur + table[digits[index]][i],index + 1);
        }

题解

class Solution {
public:
    map<char, string> table;

    void init() {
        table['2'] = "abc";
        table['3'] = "def";
        table['4'] = "ghi";
        table['5'] = "jkl";
        table['6'] = "mno";
        table['7'] = "pqrs";
        table['8'] = "tuv";
        table['9'] = "wxyz";
    }

    int len;
    vector<string> ret;

    vector<string> letterCombinations(const string &digits) {
        init();
        len = digits.length();
        if(len==0) return ret;
        dfs(digits, "",0);
        return ret;
    }

    void dfs(string digits, const string &cur,int index) {
        if (index == len) {
            ret.push_back(cur);
            return;
        }
        for(int i=0;i<table[digits[index]].length();i++){
            dfs(digits,cur + table[digits[index]][i],index + 1);
        }

    }
};

括号生成

问题描述

给出 n 代表生成括号的对数,请你写出一个函数,使其能够生成所有可能的并且有效的括号组合。
例如,给出 n = 3,生成结果为:

[
  "((()))",
  "(()())",
  "(())()",
  "()(())",
  "()()()"
]

思路

本题用了回溯算法来生成括号组合。

在最开始需要注意的地方是,n是括号的对数,所以递归的步数应该是n=n*2。
每次递归的选择只有‘(’和“)”两种选择。
当递归的次数到达n时在返回上一层递归时,要先判断是不是有效的括号组合,如果是有效的括号组合,则将括号组合插入到返回结果vector<int> A中。
返回上一层递归后,删除字符串的最一个字符用 str.substr(0, str.length() - 1)

判断字符是否为有效括号组合

如果字符为“(”,那么将其push到栈中,如果为“)”那么在栈中弹出一个“)”。
当栈为空的时候弹出“)”则直接可以判断不是一个有效的括号组合。
到最后的时候栈不为空,则说明“(”比较多,也说明不是有效的括号组合。

题解


class Solution {
public:
    vector<string> A;

    vector<string> generateParenthesis(int n) {
        n = n * 2;
        dfs(n, 0, A);
        return A;
    }

    string str;

    void dfs(int n, int step, vector<string> &A) {

        if (step == n) {
            if (alter(str) == 0) {
                A.push_back(str);
            }
            return;
        }
        for (int i = 0; i < 2; i++) {
            if (i == 0) {
                str = str + "(";
            } else {
                str += ")";
            }
            dfs(n, step + 1, A);
            str = str.substr(0, str.length() - 1);
        }
    }

    int alter(string string1) {
        stack<string> stack1;
        int n = string1.length();
        for (int i = 0; i < n; i++) {
            if (string1[i] == '(') {
                stack1.push("(");
            } else if (string1[i] == ')') {
                if (!stack1.empty()) { stack1.pop(); }
                else {return -1;}
            }
        }
        if (stack1.empty()) {
            return 0;
        } else {
            return -1;
        }
    }
};

删除链表的倒数第N个节点

问题描述

给定一个链表,删除链表的倒数第 n 个节点,并且返回链表的头结点。

示例:
给定一个链表: 1->2->3->4->5, 和 n = 2.
当删除了倒数第二个节点后,链表变为 1->2->3->5.

说明:
给定的 n 保证是有效的。

进阶:
你能尝试使用一趟扫描实现吗?

来源:力扣(LeetCode)
链接:https://leetcode-cn.com/problems/remove-nth-node-from-end-of-list

思路

本题中需要删除链表中的倒数第n个节点,因此,求出链表长度len后,将此问题转化为删除链表中第len1=len-n个节点。
问题转化后,就是一个简单的遍历加删除节点的问题。

题解

class Solution {
public:
    ListNode *removeNthFromEnd(ListNode *head, int n) {
        int len = 1;
        ListNode *p = head;
        while (p->next != nullptr) {
            len++;
            p = p->next;
        }
        int len1 = len - n;
        if(len1==0){
            return head->next;
        }
        else{
            Find(head, len1);
            return head;
        }
    }
    int lo = 1;
    void Find(ListNode *&node, int n) {
       ListNode *p=node;
       while (lo<n){
           lo++;
           p=p->next;
       }
       p->next=p->next->next;
    }
};

最长回文子串

问题描述

给定一个字符串 s,找到 s 中最长的回文子串。你可以假设 s 的最大长度为 1000。

示例 1:
输入: "babad"
输出: "bab"
注意: "aba" 也是一个有效答案。

示例 2:
输入: "cbbd"
输出: "bb"

来源:力扣(LeetCode)
链接:https://leetcode-cn.com/problems/longest-palindromic-substring

思路

初始状态:
dpi=1; //单个字符是回文串
dpi=1 if s[i]=s[i+1]; //连续两个相同字符是回文串

状态转移:s[i]==s[j]时,si+1==1——>dpi=1;

题解

实现代码:

class Solution {
public:
    string longestPalindrome(string s) {
        int len=s.size();
        if(len==0||len==1)
            return s;
        int start=0;//回文串起始位置
        int max=1;//回文串最大长度
        vector<vector<int>>  dp(len,vector<int>(len));//定义二维动态数组
        for(int i=0;i<len;i++)//初始化状态
        {
            dp[i][i]=1;
            if(i<len-1&&s[i]==s[i+1])
            {
                dp[i][i+1]=1;
                max=2;
                start=i;
            }
        }
        for(int l=3;l<=len;l++)//l表示检索的子串长度,等于3表示先检索长度为3的子串
        {
            for(int i=0;i+l-1<len;i++)
            {
                int j=l+i-1;//终止字符位置
                if(s[i]==s[j]&&dp[i+1][j-1]==1)//状态转移
                {
                    dp[i][j]=1;
                    start=i;
                    max=l;
                }
            }
        }
        return s.substr(start,max);//获取最长回文子串
    }
};
作者:gpe3DBjDS1
链接:https://leetcode-cn.com/problems/two-sum/solution/zui-chang-hui-wen-zi-chuan-c-by-gpe3dbjds1/