11.称最多水的容器¶
class Solution {
public:
int maxArea(vector<int>& height) {
int n=height.size();
if(n==1) return 0;
int left=0;
int right=n-1;
int m=0;
int max=0;
int now;
while(right-left>0){
m=std::min(height[left],height[right]);
now=(right-left)*m;
if(now>max) max=now;
if(m==height[left]){
while(left<right&&height[left]<=m) left++;
}else{
while(left<right&&height[right]<=m) right--;
}
}
return max;
双指针法,可以将时间复杂度降低到O(1)量级。注意本题内层while判断条件不要漏了left < right,否则循环可能永远停不下来。
12.整数转罗马数字¶
const pair<int,string> values[]={
{1000,"M"},{900,"CM"},{500,"D"},{400,"CD"},{100,"C"},{90,"XC"},{50,"L"},{40,"XL"},{10,"X"},{9,"IX"},{5,"V"},
{4,"IV"},{1,"I"}
};
class Solution {
public:
string intToRoman(int num) {
string a;
for(auto const [v,s]:values){
while(num>=v){
num-=v;
a+=s;
}
if(num==0) break;
}
return a;
}
};
同时,关于pair的用法,可以用std::make_pair(a,b)构建一个pair
方法二其实更加简单,就是用标准字符串的加法。如下
const string thousands[] = {"", "M", "MM", "MMM"};
const string hundreds[] = {"", "C", "CC", "CCC", "CD", "D", "DC", "DCC", "DCCC", "CM"};
const string tens[] = {"", "X", "XX", "XXX", "XL", "L", "LX", "LXX", "LXXX", "XC"};
const string ones[] = {"", "I", "II", "III", "IV", "V", "VI", "VII", "VIII", "IX"};
class Solution {
public:
string intToRoman(int num) {
return thousands[num / 1000] + hundreds[num % 1000 / 100] + tens[num % 100 / 10] + ones[num % 10];
}
};
13.罗马数字转成整数¶
枚举所有情况即可
class Solution {
public:
int romanToInt(string s) {
int num=0;
int i=0;
int n=s.size();
while(i<n){
if(s[i]=='M') {num+=1000;i++;}
if(s[i]=='D') {num+=500;i++;}
if(s[i]=='C') {
if(s[i+1]=='M'){num+=900;i+=2;}
else if(s[i+1]=='D'){num+=400;i+=2;}
else{num+=100;i++;}
}
if(s[i]=='X'){
if(s[i+1]=='C'){num+=90;i+=2;}
else if(s[i+1]=='L'){num+=40;i+=2;}
else{num+=10;i++;}
}
if(s[i]=='L'){num+=50;i++;}
if(s[i]=='V'){num+=5;i++;}
if(s[i]=='I'){
if(s[i+1]=='X'){num+=9;i+=2;}
else if(s[i+1]=='V'){num+=4;i+=2;}
else{num+=1;i++;}
}
}
return num;
}
};
最长公共前缀¶
class Solution {
public:
string longestCommonPrefix(vector<string>& strs) {
string a;
int i=0;
while(strs[0][i]==strs[1][i]&&strs[0][i]==strs[2][i]){
a+=strs[0][i];
i++;
}
return a;
}
};
正确的做法如下:
class Solution {
public:
string longestCommonPrefix(vector<string>& strs) {
// if(strs.empty()) return "";
int n=strs.size();
string a;
for(int i=0;i<strs[0].size();i++){
for(int j=0;j<n;j++){
if(strs[j][i]!=strs[0][i]||i>strs[j].size()){
return a;
}
}
a+=strs[0][i];
}
return a;
}
};
难度普通
15.三数之和¶
这道题是第一题两数之和的加强版
方法一仍然用哈希表的方法,这个方法时间复杂度为O(nn),关键在于每一步的严谨性,首先要将nums[]排序,从而跳过重复的。其次,应该在遍历第一层i循环过程中每次新建一个哈希表,不可一开始在双循环外面直接建立哈希表。并且,关于i和j的跳过重复的操作还是有点复杂的
class Solution {
public:
vector<vector<int>> threeSum(vector<int>& nums) {
vector<vector<int>> ans;
std::sort(nums.begin(), nums.end()); // 先对数组进行排序
for(int i=0;i<nums.size();i++){
if(i>0&&nums[i]==nums[i-1]) continue;
unordered_map<int,int> hash;
for(int j=i+1;j<nums.size();j++){
//if(j>0&&nums[j]==nums[j-1]) continue;
auto it = hash.find(-nums[i]-nums[j]);
if(it!=hash.end()){
ans.push_back({nums[i],nums[j],it->first});
while(j+1<nums.size()&&nums[j]==nums[j+1]) j++;
}
//hash[nums[i]]=i;
hash[nums[j]]=j;
}
}
return ans;
}
};
class Solution {
public:
vector<vector<int>> threeSum(vector<int>& nums) {
vector<vector<int>> ans;
int n=nums.size();
std::sort(nums.begin(),nums.end());
int third;
for(int first=0;first<n;first++){
if(first>0&&nums[first]==nums[first-1]) continue;
third=n-1;
for(int second=first+1;second<n;second++){
if(second>first+1 && nums[second]==nums[second-1]) continue;
while(second<third&&nums[first]+nums[second]+nums[third]>0) third--;
if(second==third)break;
if(nums[first]+nums[second]+nums[third]==0) ans.push_back({nums[first],nums[second],nums[third]});
}
}
return ans;
}
};
17.最接近的三数之和¶
class Solution {
public:
int threeSumClosest(vector<int>& nums, int target) {
int n= nums.size();
int best=1e5;
int current;
int second;
int third;
std::sort(nums.begin(),nums.end());
for(int first=0;first<n;first++){
second=first+1;
third=n-1;
while(second<third){
int sum=nums[first]+nums[second]+nums[third];
if(sum==target) return target;
if(abs(sum-target)<abs(best-target)) best = sum;
if(sum>target){
third--;
}else{
second++;
}
}
}
return best;
}
};
17.电话号码的字母组合¶
这是一道很经典的回溯算法题,同时也是对c++各种容器操作、语法运用的经典。本人的解答:
void backtrack(vector<string> &ans,string &a,int index,string &digits,unordered_map<char,string> &phonemap){
if(index==digits.length()){
ans.push_back(a);
}
char k = digits[index];
for(char c:phonemap[k]){
a.push_back(c);
backtrack(ans,a,index+1,digits,phonemap);
a.pop_back();
}
}
class Solution {
public:
vector<string> letterCombinations(string digits) {
if(digits.empty()) return {};
unordered_map<char,string> phonemap{
{'2',"abc"},{'3',"def"},{'4',"ghi"},
{'5',"jkl"},{'6',"mno"},{'7',"pqrs"},
{'8',"tuv"},{'9',"wxyz"}
};
string a;
vector<string> ans;
backtrack(ans,a,0,digits,phonemap);
return ans;
}
};
cpp char digit = digits[index];
const string& letters = phoneMap.at(digit);
for (const char& letter: letters) {
19.删除列表的倒数第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 *dump= new ListNode(0,head);
ListNode *tempt=new ListNode;
tempt=head;
int l=0;
while (tempt){
l++;
tempt=tempt->next;
}
tempt=dump;
if(l==n) return head->next;
for(int i=0;i<l-n;i++){
tempt=tempt->next;
}
tempt->next=tempt->next->next;
return head;
}
};
复习一下链表吧,顺便把c++中的new函数用熟练,例如本题中ListNode* dump=new ListNode(0,head);同时,链表经常建立一个空表头来避免对头节点的分类讨论。还蛮好的一道基础题。
20.有效的括号¶
class Solution {
public:
bool isValid(string s) {
int n=s.size();
if(n%2==1) return false;
stack<char> stk;
unordered_map<char,char> m={
{')','('},{']','['},{'}','{'}
};
for(char c:s){
if(m.count(c)){
if(stk.empty()||stk.top()!=m[c]){
return false;
}else{
stk.pop();
}
}else{
stk.push(c);
}
}
return stk.empty();
}
};
或者用简单的方法,直接枚举三种情况:
class Solution {
public:
bool isValid(string s) {
stack<int> st;
for (int i = 0; i < s.size(); i++) {
if (s[i] == '(' || s[i] == '[' || s[i] == '{') st.push(i);
else {
if (st.empty()) return false;
if (s[i] == ')' && s[st.top()] != '(') return false;
if (s[i] == '}' && s[st.top()] != '{') return false;
if (s[i] == ']' && s[st.top()] != '[') return false;
st.pop();
}
}
return st.empty();
}
};