首页 > 其他分享 >Leetcode11~20题整理

Leetcode11~20题整理

时间:2023-05-07 15:22:44浏览次数:55  
标签:20 nums int res next Leetcode11 整理 return size

11. 盛最多水的容器

比较暴力的做法:

class Solution {
public:
    int maxArea(vector<int>& h) {
        vector<int> t;
        int n = h.size();
        int res = -1;
        for(int i = 0; i < n; i++) {
            for(int j = 0; j < (int)t.size(); j++) {
                res = max(res, (i - t[j]) * min(h[i], h[t[j]]));
            }
            if(!t.size() || h[i] > h[t.back()]) t.push_back(i);
        }

        return res;
    }
};

正解,双指针

class Solution {
public:
    int maxArea(vector<int>& h) {
        int i = 0, j = h.size() - 1;
        int res = 0;
        while(i < j) {
            res = max(res, (j - i) * min(h[j], h[i]));
            if(h[i] > h[j]) j--;
            else i++;
        }
        return res;
    }
};

12. 整数转罗马数字

找规律,将几个特殊的表示存下来,

比如num = 1254, res = ""

1254 ≥ 1000,则num = 1254 - 1000 = 254, res = "M"

254 ≥ 100, num = 254 - 100 = 154, res = "MC"

154 ≥ 100, num = 154 - 100 = 54, res = "MCC"

54 ≥ 50. num = 54 - 50 = 4, res = "MCCL"

4 ≥ 4, num = 4 - 4 = 0, res = "MCCLIV"

class Solution {
public:
    string intToRoman(int num) {
        int values[] = {
            1000,
            900, 500, 400, 100,
            90, 50, 40, 10,
            9, 5, 4, 1
        };
        string reps[] = {
            "M",
            "CM", "D", "CD", "C",
            "XC", "L", "XL", "X",
            "IX", "V", "IV", "I"
        };
        
        string res = "";
        for(int i = 0; i < 13; i++) {
            while(num >= values[i]) {
                num -= values[i];
                res += reps[i];
            }
        }

        return res;
    }
};

13. 罗马数字转整数

特殊情况是下面几个,其他的都是直接将字符表示的阿拉伯数字相加,所以遇到一个字符表示的阿拉伯数字比后面字符的阿拉伯数字要小的话说明就是下面这种情况

I 可以放在 V (5) 和 X (10) 的左边,来表示 4 和 9。
X 可以放在 L (50) 和 C (100) 的左边,来表示 40 和 90。 
C 可以放在 D (500) 和 M (1000) 的左边,来表示 400 和 900。

class Solution {
public:
    int romanToInt(string s) {
        unordered_map<char, int> hs;
        hs['I'] = 1, hs['V'] = 5;
        hs['X'] = 10, hs['L'] = 50,
        hs['C'] = 100, hs['D'] = 500,
        hs['M'] = 1000;

        int res = 0;
        for(int i = 0; i < s.size(); i++) {
            if(i + 1 < s.size() && hs[s[i]] < hs[s[i + 1]]) {
                res -= hs[s[i]];
            }else {
                res += hs[s[i]];
            }
        }

        return res;
    }
};

14. 最长公共前缀

以第一个字符串为基准,不断增加公共前缀的长度,直到strs中有任何一个字符串不满足即退出

方法一:

会造成很多冗余匹配,复杂度较高

class Solution {
public:
    string longestCommonPrefix(vector<string>& strs) {
        if (!strs.size()) {
            return "";
        }
        string prefix = strs[0];
        int count = strs.size();
        for (int i = 1; i < count; ++i) {
            prefix = longestCommonPrefix(prefix, strs[i]);
            if (!prefix.size()) {
                break;
            }
        }
        return prefix;
    }

    string longestCommonPrefix(const string& str1, const string& str2) {
        int length = min(str1.size(), str2.size());
        int index = 0;
        while (index < length && str1[index] == str2[index]) {
            ++index;
        }
        return str1.substr(0, index);
    }
};

方法二:

最多遍历所有字符串的字符个数之和

class Solution {
public:
    string longestCommonPrefix(vector<string>& strs) {
        string res = "";
        if(strs.size() == 0) return res;

        for(int i = 0; ; i++){
            if(i >= strs[0].size()) return res;
            char ch = strs[0][i];
            for(int j = 1; j < strs.size(); j++) {
                if(i >= strs[j].size() || strs[j][i] != ch) {
                    return res;
                }
            }
            res += ch;
        }

        return res;
    }
};

15. 三数之和

为了避免重复,我们保证三个数对以不降序排列,所有需要先将整个数组排序

枚举第一个数字然后转换成两数之和的问题,这里的两数之和要求找到所有满足条件的而不是像第一题那样只用找一个,所以要用双指针算法来找,具体如下:

sum = nums[i] + nums[j]

  • sum > tar,则i往左走,令sum变小
  • sum < tar,则j往右走,令sum变大
  • sum == tar,则表示找到了一对,此时i往右走,j往左走,在此期间为了枚举重复,需要在指针移动的时候判重
class Solution {
public:
    vector<vector<int>> twoSum(vector<int>& nums, int l, int r, int tar, int x) {
        vector<vector<int>> res;
        for(int i = l, j = r; i < j;) {
            if(nums[i] + nums[j] < tar) {
                i++;
            }else if(nums[i] + nums[j] > tar) {
                j--;
            }else {
                res.push_back({x, nums[i], nums[j]});
                while(i < j && nums[i] == nums[i + 1]) i++;
                while(i < j && nums[j] == nums[j - 1]) j--;
                i++, j--;
            }
        }
        return res;
    }
    vector<vector<int>> threeSum(vector<int>& nums) {
        int n = nums.size();
        sort(nums.begin(), nums.end());
        vector<vector<int>> res;
        for(int i = 0; i < n; i++) {
            if(i && nums[i] == nums[i - 1]) continue;
            auto t = twoSum(nums, i + 1, n - 1, -nums[i], nums[i]);
            res.insert(res.end(), t.begin(), t.end());
        }

        return res;
    }
};

试探性的减:

class Solution {
public:
    vector<vector<int>> threeSum(vector<int>& nums) {
        vector<vector<int>> res;
        sort(nums.begin(), nums.end());
        for(int i = 0; i < nums.size(); i++) {
            if(i && nums[i] == nums[i - 1]) continue;
            for(int j = i + 1, k = nums.size() - 1; j < k; j++) {
                if(j > i + 1 && nums[j] == nums[j - 1]) continue;
                while(j < k - 1 && nums[i] + nums[j] + nums[k - 1] >= 0) k-- ;
                if(nums[i] + nums[j] + nums[k] == 0) {
                    res.push_back({nums[i], nums[j], nums[k]});
                }
            }
        }

        return res;
    }
};

16. 最接近的三数之和

和上一题差不多,只不过是需要找到大于等于target最小的三数和以及小于等于target最大的三数和,然后两个差值的绝对值取最小值对应的和就是答案

class Solution {
public:
    int threeSumClosest(vector<int>& nums, int target) {
        int n = nums.size();
        sort(nums.begin(), nums.end());
        pair<int, int> res(INT_MAX, INT_MAX);
        for(int i = 0; i < n; i++) {
            if(i && nums[i] == nums[i - 1]) continue;
            for(int j = i + 1, k = n - 1; j < k; j++) {
                while(j < k - 1 && nums[i] + nums[j] + nums[k - 1] >= target) k--;
                int sum = nums[i] + nums[j] + nums[k];
                res = min(res, {abs(sum - target), sum});

                if(k - 1 > j) {
                    sum = nums[i] + nums[j] + nums[k - 1];
                    res = min(res, {target - sum, sum});
                }
            }
        }
        return res.second;
    }
};

17. 电话号码的字母组合

dfs爆搜

class Solution {
public:
    string hs[11] = {"", "", "abc", "def", "ghi", "jkl", "mno", "pqrs", "tuv", "wxyz"};
    vector<string> res;
    void dfs(int u, string s, string digits) {
        if(u == digits.size()) {
            if(s != "")
                res.push_back(s);
            return ;
        }
        int idx = digits[u] - '0';
        for(auto c : hs[idx]) {
            s = s + c;
            dfs(u + 1, s, digits);
            s.pop_back();
        }
    }
    vector<string> letterCombinations(string digits) {

        dfs(0, "", digits);

        return res;
    }
};

18. 四数之和

和三数之和一样,只不过是枚举i和j,然后k和u使用双指针算法

class Solution {
public:
    vector<vector<int>> fourSum(vector<int>& nums, int target) {
        int n = nums.size();
        sort(nums.begin(), nums.end());
        vector<vector<int>> res;
        for(int i = 0; i < n; i++) {
            if(i && nums[i] == nums[i - 1]) continue;
            for(int j = i + 1; j < n; j++) {
                if(j > i + 1 && nums[j] == nums[j - 1]) continue;
                for(int k = j + 1, u = n - 1; k < u; k++) {
                    if(k > j + 1 && nums[k] == nums[k - 1]) continue;
                    while(k < u - 1 && 1ll * nums[i] + nums[j] + nums[k] + nums[u - 1] >= target) u--;
                    if(1ll * nums[i] + nums[j] + nums[k] + nums[u] == target) {
                        res.push_back({nums[i], nums[j], nums[k], nums[u]});
                    }
                }
            }
        }

        return res;
    }
};

19. 删除链表的倒数第 N 个结点

方法一:

先对链表进行一次遍历,得到节点总数,然后遍历倒数第n+1个点(因为删除时需要知道前面一个点),也就是从前往后第tot - n 个点

/**
 * Definition for singly-linked list.
 * struct ListNode {
 *     int val;
 *     ListNode *next;
 *     ListNode() : val(0), next(nullptr) {}
 *     ListNode(int x) : val(x), next(nullptr) {}
 *     ListNode(int x, ListNode *next) : val(x), next(next) {}
 * };
 */
class Solution {
public:
    ListNode* removeNthFromEnd(ListNode* head, int n) {
        ListNode* dummy = new ListNode(-1);
        dummy->next = head;
        int tot = 0;
        ListNode* p = dummy->next;
        while(p) {
            tot++;
            p = p->next;
        }
        int cur = 0;
        p = dummy;
        while(cur < (tot - n)) {
            p = p->next;
            cur++;
        }
        p->next = p->next->next;

        return dummy->next;
    }
  };

方法二:

快慢指针

设置两个指针p1p2,让快指针p1先走 n步,然后两个指针再同时走。当第二个指针走到最后时,第一个指针的位置就是需要被删除的节点。

由于我们设置了虚拟头节点dummy,所以当开始p1p2都在dummy时,p1n步,然后同时走,最后p2停止的位置就是倒数第n+1个节点

/**
 * Definition for singly-linked list.
 * struct ListNode {
 *     int val;
 *     ListNode *next;
 *     ListNode() : val(0), next(nullptr) {}
 *     ListNode(int x) : val(x), next(nullptr) {}
 *     ListNode(int x, ListNode *next) : val(x), next(next) {}
 * };
 */
class Solution {
public:
    ListNode* removeNthFromEnd(ListNode* head, int n) {
        ListNode* dummy = new ListNode(-1);
        dummy->next = head;
        ListNode* p1 = dummy;
        ListNode* p2 = dummy;
        while(n--) p1 = p1->next;
        while(p1->next) {
            p1 = p1->next;
            p2 = p2->next;
        }
        p2->next = p2->next->next;
        
        return dummy->next;
    }
};

20. 有效的括号

维护一个栈,如果是左括号就将其入栈, 如果是右括号就拿栈顶元素出来看是否匹配

class Solution {
public:
    bool isValid(string s) {
        stack<char> stk;
        for(auto c : s) {
            if(c == '(' || c == '[' || c == '{') stk.push(c);
            else {
                if(stk.size()) {
                    char top = stk.top();
                    if((c == ')' && top == '(')  || (c == '}' && top == '{') || (c == ']' && top == '[')) {
                        stk.pop();
                    }else {
                        return false;
                    }
                }else {
                    return false;
                }
            }
        }
        if(stk.size()) return false;
        else return true;
    }
};

标签:20,nums,int,res,next,Leetcode11,整理,return,size
From: https://www.cnblogs.com/junlin623/p/17379367.html

相关文章

  • 使用IDEA2023创建springMVC项目,web项目
    1.使用idea2022创建web项目 2.新建模块 3.编写文件名,记住如果想单独一个项目,不想被包括在其他项目里面就取消位置后面的地址,它有可能是上一个项目的主文件 4.创建完主要项目以后要添加web模块,先选中需要添加web项目的模块,再店家上方+号,选择 web模块 3.修改部......
  • DELL-G15 5520蓝屏自动修复
    由于戴尔网卡的原因,会导致蓝屏,更新驱动无用,进入BIOS解决问题如下可用:蓝屏代码DRIVER_VERIFIER_DMAVIOLATION12解决方案:机器关机开机连续按F2选择倒数第三个选项把EnablePre-BootDMASupport改为OFF把EnableOSKernelDMASupport改为OFF最后点击APPL保存即可......
  • .NET周报 【4月第5期 2023-04-30】
    国内文章基于Github平台的.NET开源项目模板.嘎嘎实用!https://www.cnblogs.com/NMSLanX/p/17326728.html大家好,为了使开源项目的维护和管理更方便一些,出于个人需求写了一款开源项目的模板,该模板基于Github平台,并使用.NET来实现管道功能.在接受过实战检验后,于今......
  • 十二代酷睿处理器N100 N200 N305 等安装ESXI紫屏问题解决办法
    12代大小核紫屏报错解决方案四部曲1、安装界面倒计时结束之前,按SHIFT+O,在原有命令后面加空格后输入以下代码cpuUniformityHardCheckPanic=FALSE2、安装完ESXI之后会重启,在重启界面倒计时结束前,再操作一次,按住SHIFT+O,输入cpuUniformityHardCheckPanic=FALSE3、进入ESXI把SSH功能......
  • 美团面经总结(2023最新)
    分享一份读者面试美团的面经,比较有参考性,感兴趣的可以看看~一面消息队列如何保证可靠性消息队列如何保证消息幂等性消息队列的优缺点为什么用b+树聚集索引和主键区别,其他引擎怎么做的平时数据库编码explain参数http报文参数有哪些吗?做题,链表奇偶有序输出二面自我介......
  • 2023.5.7——软件工程日报
    所花时间(包括上课):6h代码量(行):0行博客量(篇):1篇今天,上午学习,下午学习并开会。我了解到的知识点:1.了解了一些数据库的知识;2.了解了一些python的知识;3.了解了一些英语知识;5.了解了一些Javaweb的知识;4.了解了一些数学建模的知识;6.了解了一些计算机网络的知识;......
  • 2023.18 星火认知大模型
    5月6日,科大讯飞正式发布星火认知大模型,宣布对外开放测试,并发布教育、办公、汽车、数字员工四大行业应用成果。星火大模型在通用能力上支持:多风格多任务长文本生成、多层次跨语种语言理解,泛领域开放式知识问答,情景式思维链逻辑推理,多题型可解析数学能力,多功能多语言代码能力。发布......
  • 2023.5.7
    1//11-62#include<iostream>3#include<fstream>4#include<string>5usingnamespacestd;6classDog7{8public:9Dog(){}10Dog(intage,intwei)11{12this->m_Age=age;13this->m_W......
  • mysql error 1064(42000)
    mysql表里面,使用同样的语法查询一张表,用的nopcommerce的表,里面的Order表,查询的时候出不来,总是提示1064(42000说语法有错误,思考不会有错,于是查询这个问题,也有想过这张表名有些特殊, 查询要加反单引号,select*from`Order`;就查询出来了,可能Order是一个关键......
  • 2023.5.6 《动手学深度学习》第3、4章
    今天继续学习《动手学习深度学习》第5章:深度学习计算、第6章:卷积神经网络,今天学到的内容主要有这两章的概念。以及实现LeNet对FashionMNIST进行分类。一、理论部分:1、概念解释:1×1卷积的作用:卷积通常用于识别相邻元素间相互作用的能力,但1×1卷积不具备该能力,其主要用于调整输......