学习平台 AcWing LeetCode究极班
LeetCode
Let 11:盛水最多的容器 * 给定一个长度为 n
的整数数组 height
。有 n
条垂线,第 i
条线的两个端点是 (i, 0)
和 (i, height[i])
。
找出其中的两条线,使得它们与 x
轴共同构成的容器可以容纳最多的水。
返回容器可以储存的最大水量。
说明: 你不能倾斜容器。
标签: 贪心
、数组
、双指针
示例 1:
1 2 3 输入:[1,8,6,2,5,4,8,3,7] 输出:49 解释:图中垂直线代表输入数组 [1,8,6,2,5,4,8,3,7]。在此情况下,容器能够容纳水(表示为蓝色部分)的最大值为 49。
示例 2:
提示:
n == height.length
2 <= n <= 105
0 <= height[i] <= 104
代码实现:
1 2 3 4 5 6 7 8 9 10 11 12 13 class Solution {public : int maxArea (vector<int >& height) { int res = 0 ; int len = height.size (); for (int i = 0 , j = len - 1 ; i < j;){ res = max (res, min (height[i], height[j]) * (j - i)); if (height[i] > height[j]) j--; else i++; } return res; } };
Let 12:整数转罗马数字 罗马数字包含以下七种字符: I
,V
, X
, L
,C
,D
和 M
。
1 2 3 4 5 6 7 8 字符 数值 I 1 V 5 X 10 L 50 C 100 D 500 M 1000
例如, 罗马数字 2 写做 II
,即为两个并列的 1。12 写做 XII
,即为 X
+ II
。 27 写做 XXVII
, 即为 XX
+ V
+ II
。
通常情况下,罗马数字中小的数字在大的数字的右边。但也存在特例,例如 4 不写做 IIII,而是 IV。数字 1 在数字 5 的左边,所表示的数等于大数 5 减小数 1 得到的数值 4 。同样地,数字 9 表示为 IX。这个特殊的规则只适用于以下六种情况:
标签: 哈希表
数学
字符串
示例 1:
示例 2:
示例 3:
示例 4:
1 2 3 输入: num = 58 输出: "LVIII" 解释: L = 50, V = 5, III = 3.
示例 5:
1 2 3 输入: num = 1994 输出: "MCMXCIV" 解释: M = 1000, CM = 900, XC = 90, IV = 4.
提示:
代码实现:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 class Solution {public : string intToRoman (int num) { string res = "" ; while (num){ if (num >= 1000 ){ int a = num / 1000 ; while (a--){ res += "M" ; } num %= 1000 ; continue ; } if (num >= 900 && num < 1000 ){ res += "CM" ; num %= 100 ; continue ; } if (num >=500 && num < 900 ){ int a = num / 100 ; res += "D" ; int sum = a - 5 ; while (sum--){ res += "C" ; } num %= 100 ; continue ; } if (num >= 400 && num < 500 ){ res += "CD" ; num %= 100 ; continue ; } if (num >= 100 && num < 400 ){ int a = num / 100 ; while (a--){ res += "C" ; } num %= 100 ; continue ; } if (num >= 90 && num < 100 ){ res += "XC" ; num %= 10 ; continue ; } if (num >= 50 && num < 90 ){ int a = num / 10 ; res += "L" ; int sum = a-5 ; while (sum--){ res += "X" ; } num %= 10 ; continue ; } if (num >= 40 && num < 50 ){ res += "XL" ; num %= 10 ; continue ; } if (num >= 10 && num < 40 ){ int a = num / 10 ; while (a--){ res += "X" ; } num %= 10 ; continue ; } if (num >= 9 && num < 10 ){ res += "IX" ; num %= 1 ; continue ; } if (num >= 5 && num < 9 ){ int a = num / 1 ; res += "V" ; int sum = a-5 ; while (sum--){ res += "I" ; } num %= 1 ; continue ; } if (num >= 4 && num < 5 ){ res += "IV" ; num %= 1 ; continue ; } if (num >= 1 && num < 4 ){ int a = num / 1 ; while (a--){ res += "I" ; } num %= 1 ; continue ; } } return res; } };
Let 13:罗马数字转整数 罗马数字包含以下七种字符: I
, V
, X
, L
,C
,D
和 M
。
1 2 3 4 5 6 7 8 字符 数值 I 1 V 5 X 10 L 50 C 100 D 500 M 1000
例如, 罗马数字 2
写做 II
,即为两个并列的 1 。12
写做 XII
,即为 X
+ II
。 27
写做 XXVII
, 即为 XX
+ V
+ II
。
通常情况下,罗马数字中小的数字在大的数字的右边。但也存在特例,例如 4 不写做 IIII,而是 IV。数字 1 在数字 5 的左边,所表示的数等于大数 5 减小数 1 得到的数值 4 。同样地,数字 9 表示为 IX。这个特殊的规则只适用于以下六种情况:
I
可以放在 V
(5) 和 X
(10) 的左边,来表示 4 和 9。
X
可以放在 L
(50) 和 C
(100) 的左边,来表示 40 和 90。
C
可以放在 D
(500) 和 M
(1000) 的左边,来表示 400 和 900。
给定一个罗马数字,将其转换成整数。
标签: 哈希表
数学
字符串
示例 1:
示例 2:
示例 3:
示例 4:
1 2 3 输入: s = "LVIII" 输出: 58 解释: L = 50, V= 5, III = 3.
示例 5:
1 2 3 输入: s = "MCMXCIV" 输出: 1994 解释: M = 1000, CM = 900, XC = 90, IV = 4.
提示:
1 <= s.length <= 15
s
仅含字符 ('I', 'V', 'X', 'L', 'C', 'D', 'M')
题目数据保证 s
是一个有效的罗马数字,且表示整数在范围 [1, 3999]
内
题目所给测试用例皆符合罗马数字书写规则,不会出现跨位等情况。
IL 和 IM 这样的例子并不符合题目要求,49 应该写作 XLIX,999 应该写作 CMXCIX 。
关于罗马数字的详尽书写规则,可以参考 罗马数字 - Mathematics 。
代码实现:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 class Solution {public : int romanToInt (string s) { int value[] = { 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" }; int res = 0 ; for (int i = 0 , j = 1 ; i < s.length (); i++, j++){ string stri = s.substr (i, 1 ); string strj = s.substr (j, 1 ); string str; int a, b; for (int k = 0 ; k < 13 ; k ++){ if (stri == reps[k]) a = k; if (strj == reps[k]) b = k; } if (b < a){ str = s.substr (i, 2 ); for (int k = 0 ; k < 13 ; k ++){ if (str == reps[k]){ res += value[k]; break ; } } i++; j++; } else { res += value[a]; } } return res; } };
Let 14:最长公共前缀 编写一个函数来查找字符串数组中的最长公共前缀。
如果不存在公共前缀,返回空字符串 ""
。
标签: 字符串
示例 1:
1 2 输入:strs = ["flower","flow","flight"] 输出:"fl"
示例 2:
1 2 3 输入:strs = ["dog","racecar","car"] 输出:"" 解释:输入不存在公共前缀。
提示:
1 <= strs.length <= 200
0 <= strs[i].length <= 200
strs[i]
仅由小写英文字母组成
代码实现:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 class Solution {public : string Juge (string str, string fl) { int len = min (str.length (), fl.length ()); int p = 0 ; for (int i = 1 ; i <= len; i ++){ string a = str.substr (0 , i); string b = fl.substr (0 , i); if (a != b && i == 1 ){ return "" ; } if (a != b && i > 1 ){ p = i - 1 ; break ; } if (a == b && i == len){ p = i; break ; } } return str.substr (0 , p); } string longestCommonPrefix (vector<string>& strs) { string str = strs[0 ]; for (int i = 1 ; i < strs.size (); i ++){ str = Juge (str, strs[i]); if (str == "" ){ return "" ; } } return str; } };
Let 15:三数之和 给你一个包含 n
个整数的数组 nums
,判断 nums
中是否存在三个元素 a,b,c ,使得 a + b + c = 0 ?请你找出所有和为 0 且不重复的三元组。
注意:答案中不可以包含重复的三元组。
标签: 数组
双指针
排序
示例 1:
1 2 输入:nums = [-1,0,1,2,-1,-4] 输出:[[-1,-1,2],[-1,0,1]]
示例 2:
示例 3:
提示:
0 <= nums.length <= 3000
-105 <= nums[i] <= 105
代码实现:
对数组进行排序后,先确定其中一个值,然后使用双指针确定另外两个值。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 class Solution {public : vector<vector<int >> threeSum (vector<int >& nums) { vector<vector<int >> res; if (nums.size () < 3 ) return res; sort (nums.begin (), nums.end ()); for (int i = 0 ; i < nums.size () - 2 ; i ++){ if (i ==0 || i != 0 && nums[i] != nums[i - 1 ]){ cout << i << endl; int a = 0 - nums[i]; int l = i + 1 , r = nums.size () - 1 ; while (l < r) { if (nums[l] + nums[r] < a){ l ++; } else if (nums[l] + nums[r] > a){ r --; } else { cout << i << endl; vector<int > arr; arr.push_back (nums[i]); arr.push_back (nums[l]); arr.push_back (nums[r]); res.push_back (arr); bool flag = false ; for (int k = l + 1 ; k < r; k++){ if (nums[k] != nums[l]){ l = k; flag = true ; break ; } } if (!flag) break ; } } } } return res; } };
Let 16:最接近的三数之和 给你一个长度为 n
的整数数组 nums
和 一个目标值 target
。请你从 nums
中选出三个整数,使它们的和与 target
最接近。
返回这三个数的和。
假定每组输入只存在恰好一个解。
标签: 数组
双指针
排序
示例 1:
1 2 3 输入:nums = [-1,2,1,-4], target = 1 输出:2 解释:与 target 最接近的和是 2 (-1 + 2 + 1 = 2) 。
示例 2:
1 2 输入:nums = [0,0,0], target = 1 输出:0
提示:
3 <= nums.length <= 1000
-1000 <= nums[i] <= 1000
-104 <= target <= 104
代码实现:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 class Solution {public : int threeSumClosest (vector<int >& nums, int target) { sort (nums.begin (), nums.end ()); int max = 100010 ; int res = 0 ; for (int i = 0 ; i < nums.size () - 2 ; i ++){ int l = i + 1 , r = nums.size () - 1 ; while (l < r){ int cnt = nums[i] + nums[l] + nums[r]; cout << cnt << endl; if (abs (cnt - target) < max){ max = abs (nums[i] + nums[l] + nums[r] - target); res = cnt; } if (cnt < target){ l++; } else if (cnt > target){ r--; } else { return target; } } } return res; } };
Let 17:电话号码的字母组合 给定一个仅包含数字 2-9
的字符串,返回所有它能表示的字母组合。答案可以按 任意顺序 返回。
给出数字到字母的映射如下(与电话按键相同)。注意 1 不对应任何字母。
标签: 哈希表
字符串
回溯
示例 1:
1 2 输入:digits = "23" 输出:["ad","ae","af","bd","be","bf","cd","ce","cf"]
示例 2:
示例 3:
1 2 输入:digits = "2" 输出:["a","b","c"]
提示:
0 <= digits.length <= 4
digits[i]
是范围 ['2', '9']
的一个数字。
代码实现:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 class Solution {public : vector<string> ans; string str[10 ] = { "" , "" , "abc" , "def" , "ghi" , "jkl" , "mno" , "pqrs" , "tuv" , "wxyz" , }; vector<string> letterCombinations (string digits) { if (digits.empty ()) return ans; dfs (digits, 0 , "" ); return ans; } void dfs (string& digits, int u, string path) { if (u >= digits.size ()) ans.push_back (path); else { int t = digits[u] - '0' ; for (auto c : str[t]){ dfs (digits, u + 1 , path + c); } } } };
Let 18:四数之和 给你一个由 n
个整数组成的数组 nums
,和一个目标值 target
。请你找出并返回满足下述全部条件且不重复的四元组 [nums[a], nums[b], nums[c], nums[d]]
(若两个四元组元素一一对应,则认为两个四元组重复):
标签: 数组
双指针
排序
示例 1:
1 2 输入:nums = [1,0,-1,0,-2,2], target = 0 输出:[[-2,-1,1,2],[-2,0,0,2],[-1,0,0,1]]
示例 2:
1 2 输入:nums = [2,2,2,2,2], target = 8 输出:[[2,2,2,2]]
提示:
1 <= nums.length <= 200
-109 <= nums[i] <= 109
-109 <= target <= 109
代码实现:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 class Solution {public : vector<vector<int >> fourSum (vector<int >& nums, int target) { sort (nums.begin (), nums.end ()); vector<vector<int >> res; if (nums.size () < 4 ) return res; for (int i = 0 ; i < nums.size () - 3 ; i++){ if (i == 0 || i != 0 && nums[i] != nums[i - 1 ]){ for (int j = i + 1 ; j < nums.size () - 2 ; j++){ if (j == i + 1 || j != i + 1 && nums[j] != nums[j - 1 ]){ int cnt = target - nums[i] - nums[j]; int l = j + 1 , r = nums.size () - 1 ; while (l < r){ if (nums[l] + nums[r] < cnt){ l++; } else if (nums[l] + nums[r] > cnt){ r--; } else { bool flag = false ; vector<int > arr{nums[i], nums[j], nums[l], nums[r]}; res.push_back (arr); for (int k = l + 1 ; k < r; k++){ if (nums[k] != nums[l]){ l = k; flag = true ; break ; } } if (!flag) break ; } } } } } } return res; } };
Let 19:删除链表的倒数第N个节点 给你一个链表,删除链表的倒数第 n
个结点,并且返回链表的头结点。
标签: 链表
双指针
示例 1:
1 2 输入:head = [1,2,3,4,5], n = 2 输出:[1,2,3,5]
示例 2:
1 2 输入:head = [1], n = 1 输出:[]
示例 3:
1 2 输入:head = [1,2], n = 1 输出:[1]
提示:
链表中结点的数目为 sz
1 <= sz <= 30
0 <= Node.val <= 100
1 <= n <= sz
代码实现:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 class Solution {public : ListNode* removeNthFromEnd (ListNode* head, int n) { ListNode *k = nullptr ; while (n--){ ListNode *p = head; while (p->next != k){ p = p -> next; } k = p; } ListNode *p = head; if (p == k){ head = k ->next; }else { while (p -> next != k){ p = p->next; } p->next = k->next; } return head; } };
Let 20:有效的括号 给定一个只包括 '('
,')'
,'{'
,'}'
,'['
,']'
的字符串 s
,判断字符串是否有效。
有效字符串需满足:
左括号必须用相同类型的右括号闭合。 左括号必须以正确的顺序闭合。
标签: 栈
字符串
示例 1:
示例 2:
示例 3:
示例 4:
示例 5:
提示:
1 <= s.length <= 104
s
仅由括号 '()[]{}'
组成
代码实现:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 class Solution {public : bool isValid (string s) { stack<char > sta; if (s.size ()==1 ){ return false ; } for (int i=0 ;i<s.size ();i++){ if (s[i] == '(' || s[i] == '[' || s[i] == '{' ){ sta.push (s[i]); }else if (sta.size ()!=0 ){ char c = sta.top (); sta.pop (); if (c == '[' && s[i] == ']' || c == '{' && s[i] == '}' || c == '(' && s[i] == ')' ){ continue ; }else { return false ; } }else if (sta.size ()==0 ){ return false ; } } if (sta.size ()!=0 ){ return false ; } return true ; } };