011. 盛最多水的容器
给你 n 个非负整数 a_1,a_2,…,a_n,每个数代表坐标中的一个点 (i, a_i) 。在坐标内画 n 条垂直线,垂直线 i 的两个端点分别为 (i, a_i) 和 (i, 0) 。找出其中的两条线,使得它们与 x 轴共同构成的容器可以容纳最多的水。
说明:你不能倾斜容器。
示例 1:
输入:[1,8,6,2,5,4,8,3,7]
输出:49
解释:图中垂直线代表输入数组 [1,8,6,2,5,4,8,3,7]。在此情况下,容器能够容纳水(表示为蓝色部分)的最大值为 49。
示例 2:
输入:height = [1,1]
输出:1
示例 3:
输入:height = [4,3,2,1,4]
输出:16
示例 4:
输入:height = [1,2,1]
输出:2
提示:
- $n height.length$
- $2 <= n <= 10^5$
- $0 <= height[i] <= 104$
AC Code
class Solution {
public:
int maxArea(vector<int>& height) {
int res=0;
for (int i=0,j=height.size()-1; i<j;)
{
res=max(res,min(height[i],height[j])*(j-i));
if (height[i]>height[j]) j--;
else i++;
}
return res;
}
};
012. 整数转罗马数字
罗马数字包含以下七种字符:I, V, X, L,C,D 和 M。
字符 数值
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:
输入: num = 3
输出: "III"
示例 2:
输入: num = 4
输出: "IV"
示例 3:
输入: num = 9
输出: "IX"
示例 4:
输入: num = 58
输出: "LVIII"
解释: L = 50, V = 5, III = 3.
示例 5:
输入: num = 1994
输出: "MCMXCIV"
解释: M = 1000, CM = 900, XC = 90, IV = 4.
提示:
- $1 <= num <= 3999$
AC Code
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<=12; i++)
{
while (num>=values[i])
{
num-=values[i];
res+=reps[i];
}
}
return res;
}
};
013. 罗马数字转整数
罗马数字包含以下七种字符: I, V, X, L,C,D 和 M。
字符 数值
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 到 3999 的范围内。
示例 1:
输入: "III"
输出: 3
示例 2:
输入: "IV"
输出: 4
示例 3:
输入: "IX"
输出: 9
示例 4:
输入: "LVIII"
输出: 58
解释: L = 50, V= 5, III = 3.
示例 5:
输入: "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 $。
AC Code
class Solution {
public:
int romanToInt(string s) {
unordered_map<char,int> hash;
hash['I']=1; hash['V']=5;
hash['X']=10; hash['L']=50;
hash['C']=100; hash['D']=500;
hash['M']=1000;
int res=0;
for (int i=0; i<s.size(); i++)
{
if (i+1<s.size() && hash[s[i]]<hash[s[i+1]])
res-=hash[s[i]];
else
res+=hash[s[i]];
}
return res;
}
};
014. 最长公共前缀
编写一个函数来查找字符串数组中的最长公共前缀。
如果不存在公共前缀,返回空字符串 “”。
示例 1:
输入:strs = ["flower","flow","flight"]
输出:"fl"
示例 2:
输入:strs = ["dog","racecar","car"]
输出:""
解释:输入不存在公共前缀。
提示:
- $1 <= strs.length <= 200$
- $0 <= strs[i].length <= 200$
- $strs[i] 仅由小写英文字母组成$
AC Code
class Solution {
public:
string longestCommonPrefix(vector<string>& strs) {
string res;
if (!strs.size()) return res;
for (int i=0; ; i++)
{
if (i>strs[0].size()) return res;
char c=strs[0][i];
for(auto &str:strs)
{
if (str.size()<=i || str[i]!=c)
return res;
}
res+=c;
}
return res;
}
};
015.三数之和
给你一个包含 n 个整数的数组 nums,判断 nums 中是否存在三个元素 a,b,c ,使得 a + b + c = 0 ?请你找出所有和为 0 且不重复的三元组。
注意:答案中不可以包含重复的三元组。
示例 1:
输入:nums = [-1,0,1,2,-1,-4]
输出:[[-1,-1,2],[-1,0,1]]
示例 2:
输入:nums = []
输出:[]
示例 3:
输入:nums = [0]
输出:[]
提示:
0 <= nums.length <= 3000
-10^5 <= nums[i] <= 10^5
题意分析
- 双指针算法
-
$i$ 的移动必须每次为不同的数
AC Code
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;
}
};
016. 最接近的三数之和
给定一个包括 n 个整数的数组 nums 和 一个目标值 target。找出 nums 中的三个整数,使得它们的和与 target 最接近。返回这三个数的和。假定每组输入只存在唯一答案。
示例:
输入:nums = [-1,2,1,-4], target = 1
输出:2
解释:与 target 最接近的和是 2 (-1 + 2 + 1 = 2) 。
提示:
3 <= nums.length <= 10^3
-10^3 <= nums[i] <= 10^3
-10^4 <= target <= 10^4
题意分析
- $nums[i]+nums[j]+nums[k]>=target\ 的最小值$
- $nums[i]+num[j]+nums[k-1]<target\ 的最大值$
AC Code
class Solution {
public:
int threeSumClosest(vector<int>& nums, int target) {
pair<int ,int> res(INT_MAX,INT_MIN);
sort(nums.begin(), nums.end());
for (int i=0; i<nums.size(); i++)
{
for (int j=i+1, k=nums.size()-1; j<k; j++)
{
while(k-1>j && nums[i]+nums[j]+nums[k-1]>=target) k--;
int sum=nums[i]+nums[j]+nums[k];
res=min(res,make_pair(abs(sum-target),sum));
if (k-1>j)
{
int sum=nums[i]+nums[j]+nums[k-1];
res=min(res,make_pair(abs(target-sum),sum));
}
}
}
return res.second;
}
};
017. 电话号码的数字组合
给定一个仅包含数字 2-9 的字符串,返回所有它能表示的字母组合。答案可以按 任意顺序 返回。
给出数字到字母的映射如下(与电话按键相同)。注意 1 不对应任何字母。
示例 1:
输入:digits = "23"
输出:["ad","ae","af","bd","be","bf","cd","ce","cf"]
示例 2:
输入:digits = ""
输出:[]
示例 3:
输入:digits = "2"
输出:["a","b","c"]
提示:
0 <= digits.length <= 4
digits[i] 是范围 [‘2’, ‘9’] 的一个数字。
AC Code
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
{
for (auto c:str[digits[u]-'0'])
dfs(digits,u+1,path+c);
}
}
};
018. 四数之和
给你一个由 n 个整数组成的数组 nums ,和一个目标值 target 。请你找出并返回满足下述全部条件且不重复的四元组 [nums[a], nums[b], nums[c], nums[d]] :
- $0 <= a, b, c, d < n$
-
a、b、c 和 d 互不相同
-
$nums[a] + nums[b] + nums[c] + nums[d] = target$
你可以按 任意顺序 返回答案 。
示例 1:
输入:nums = [1,0,-1,0,-2,2], target = 0
输出:[[-2,-1,1,2],[-2,0,0,2],[-1,0,0,1]]
示例 2:
输入:nums = [2,2,2,2,2], target = 8
输出:[[2,2,2,2]]
提示:
1 <= nums.length <= 200
-10^9 <= nums[i] <= 10^9
-10^9 <= target <= 10^9
AC Code
class Solution {
public:
vector<vector<int>> fourSum(vector<int>& nums, int target) {
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; j<nums.size(); j++)
{
if (j>i+1 && nums[j]==nums[j-1]) continue;
for (int k=j+1, u=nums.size()-1; k<u; k++)
{
if (k>j+1 && nums[k]==nums[k-1]) continue;
while(k<u-1 && nums[i]+nums[j]+nums[k]+nums[u-1]>=target) u--;
if (nums[i]+nums[j]-target==-nums[k]-nums[u]) //防止溢出
res.push_back({nums[i],nums[j],nums[k], nums[u]});
}
}
}
return res;
}
};
019. 删除链表的倒数第N个节点
给你一个链表,删除链表的倒数第 n 个结点,并且返回链表的头结点。
进阶:你能尝试使用一趟扫描实现吗?
示例 1:
输入:head = [1,2,3,4,5], n = 2
输出:[1,2,3,5]
示例 2:
输入:head = [1], n = 1
输出:[]
示例 3:
输入:head = [1,2], n = 1
输出:[1]
提示:
链表中结点的数目为 sz
1 <= sz <= 30
0 <= Node.val <= 100
1 <= n <= sz
AC Code
/**
* 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) {
auto dummy=new ListNode(-1); //创建虚拟头节点
dummy->next=head;
int len=0;
for (auto p=dummy; p!=NULL; p=p->next) len++;
auto p=dummy;
for (int i=0; i<len-n-1; i++) p=p->next;
p->next=p->next->next;
return dummy->next;
}
};
020. 有效的括号
给定一个只包括 '('
,')'
,'{'
,'}'
,'['
,']'
的字符串 s
,判断字符串是否有效。
有效字符串需满足:
- 左括号必须用相同类型的右括号闭合。
- 左括号必须以正确的顺序闭合。
示例 1:
输入:s = "()"
输出:true
示例 2:
输入:s = "()[]{}"
输出:true
示例 3:
输入:s = "(]"
输出:false
示例 4:
输入:s = "([)]"
输出:false
示例 5:
输入:s = "{[]}"
输出:true
提示:
1 <= s.length <= 104
s
仅由括号'()[]{}'
组成
AC Code
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() && abs(stk.top()-c)<=2) stk.pop();
else return false;
}
}
return stk.empty();
}
};
0 条评论