文章目录
- 11.盛最多水的容器
- C++版本
- Python版本
- 12.整数转罗马数字
- C++版本
- Python
- 13.罗马数字转整数
- C++版本
- Python版本
- 14.查找字符串数组的最长公共前缀
- C++版本
- Python版本
- 15.三数之和
- C++版本
- Python版本
- 16.最接近的三数之和
- C++版本
- Python
- 17.电话号码的字母组合
- C++版本
- Python版本
- 18.四数之和
- C++版本
- Python版本
- 19.删除链表的倒数第N个节点
- C++版本
- Python 版本
- 20.有效的括号
- C++版本
- Python 版本
 感觉C++语言的算法比Python更有趣,以后还是将C++放在前面。
11.盛最多水的容器
给定一组数据,每两对数据做木桶理论求能盛的最大的水,例如我们假设一组数据第一个数和第三个数,其面积为两者索引的差*两者中较小的数。
算法思想:通过两端向中间叠进(不知道名字,双指针法?),可以有效降低时间复杂度;设置left和right变更的条件,同样可以减少判断次数,如当我们需要变更left时,变更后再比较left和left+1,如果索引left+1的值>索引left的值,则可以继续将left+1。
C++版本
class Solution{
public:
    int maxArea(vector<int> &height){
        int maxArea = 0;
        int left = 0;
        int right = height.size()-1;
        int area;
        while(left<right){
            area = (right-left)*(height[left]<height[right]? height[left]:height[right]);
            maxArea = area>maxArea? area:maxArea;
            cout<<height[left]<<"--"<<height[right]<<endl;
            if(height[left]<height[right]){
                do{
                    left++;
                }while (left<right && height[left+1]>height[left]);
            }
            else{
                do{
                    right--;
                    //cout<<(height[right])<<endl;
                }while (right>left && (height[right-1]>height[right]));
            }
        }
        return maxArea;
    }
};
int main(){
    vector<int> height {3,4,5,7,1,4,1};
    int area;
    Solution s;
    area = s.maxArea(height);
    cout<<area<<endl;
    return 0;
}Python版本
Python版本的代码没有做太多优化
def maxarea(height):
# height: list[int]
ans = left = 0
right = len(height)-1
while left<right:
ans = max(ans,(right-left)*min(height[left],height[right]))
if height[left] <= height[right]:
left += 1
else:
right -= 1
return ans
print(maxarea([1,2,3,4]),maxarea([3,4,5,7,1,4,1]))
12.整数转罗马数字
将整数转化为罗马数字。
算法思想:这里不赘述了,直接代码可以看懂。
C++版本
string inttoRoman(int num){
    string symbol[] = {"M","CM","D","CD","C","XC","L","XL","X","IX","V","IV","I"};
    int value[] = {1000,900,500,400,100,90,50,40,10,9,5,4,1};
    string result;
    for(int i=0;num!=0;i++){
        while (num>=value[i]) {
            num -= value[i];
            result += symbol[i];
        }
    }
    return result;
}
int main(int argc,char** argv){
    int num=1234;
    string result;
    result = inttoRoman(num);
    cout<<num<<"\n"<<result<<endl;
    return 0;
}Python
class Solution(object):
def inttoRoman(self,num):
ans = ""
values = {"M":1000,"D":500,"C":100,"L":50,"X":10,"V":5,"I":1}
literals = ["M","D","C","L","X","V","I"]
for idx in [0,2,4]:
k = num // values[literals[idx]]
re = (num % values[literals[idx]]) // values[literals[idx+2]]
ans += k*literals[idx]
if re >= 9:
ans += literals[idx+2] + literals[idx]
elif re >= 5:
ans += literals[idx+1] + literals[idx+2] * (re-5)
elif re == 4:
ans += literals[idx+2] + literals[idx+1]
else:
ans += re * literals[idx+2]
num %= values[literals[idx+2]]
return ans
te1 = Solution()
print(te1.inttoRoman(1234),te1.inttoRoman(999),te1.inttoRoman(495))
13.罗马数字转整数
12题的反向,将罗马数字转化为整数
算法思想:处理好当前数字小于后面数字的情况
C++版本
int romanchar2int(char ch){
    int d=0;
    switch (ch) {
        case 'M':
            d = 1000;
            break;
        case 'D':
            d = 500;
            break;
        case 'C':
            d = 100;
            break;
        case 'L':
            d = 50;
            break;
        case 'X':
            d = 10;
            break;
        case 'V':
            d = 5;
            break;
        case '1':
            d = 1;
            break;
    }
    return d;
};
int roman2int(string s){
    if(s.size()<=0) return 0;
    int result = romanchar2int(s[0]);
    for (int i=1; i<s.size(); i++) {
        int pre = romanchar2int(s[i-1]);
        int cur = romanchar2int(s[i]);
        if (pre < cur){
            result -= pre + pre;
        }
        result += cur;
        
    }
    return result;
}
int main(int argc,char**argv){
    string s("XL");
    int num = roman2int(s);
    cout<<s<<":"<<num<<endl;
}int roman2Int(string rom){
    map<string,int> r2i= {{"M",1000},{"CM",900},{"D",500},{"CD",400},{"C",100},{"XC",90},{"L",50},{"XL",40},{"X",10},{"IX",9},{"V",5},{"IV",4},{"I",1}};
    int num = 0;
    string str,str2;
    for(int i=0;i<rom.size();i++){
        str = rom[i];
        str2 = rom[i];
        //cout<<"str:"<<str<<endl;
        if (r2i.find(str) != r2i.end()){
            if (i<rom.size()-1){
                str2 += rom[i+1];
                //cout<<"str2:"<<str2<<endl;
                if(r2i.find(str2) != r2i.end()) {
                    num += r2i[str2];
                    i++;
                }
                else num += r2i[str];
            }
            else num += r2i[str];
        }
        else return 0;
    }
    return num;
}
int main(int argc,char**argv){
    string s("MCDLI");
    int num = roman2Int(s);
    cout<<s<<":"<<num<<endl;
}Python版本
def roman2int(s):
d = {"I":1,"V":5,"X":10,"L":50,"C":100,"D":500,"M":1000}
ans = d[s[0]]
for i in range(1,len(s)):
if (d[s[i-1]]<d[s[i]]):
ans += d[s[i]] - 2 * d[s[i-1]]
else:
ans += d[s[i]]
return ans
print(roman2int("MCCXL"))
14.查找字符串数组的最长公共前缀
题目可以说明问题这里不啰嗦
算法思想:这里我有两种思路,一是采用两个for循环,循环第一个字符串+循环字符数组;第二种思路是对第一个字符串采用二分法+for循环。
C++版本
string longestPrefix(vector<string> &strs){
    string pre;
    if (strs.size()<=0 || strs[0].size()<=0) return "";
    int right = strs[0].size();
    int preright = strs[0].size();
    int preleft = 0;
    while(preleft<right){
        for (int i=0;i<strs.size();i++){
            if(strs[i].size()<right) {
                preright = right;
                right = (right+preleft)/2;
                break;
            }
            if (strs[0].substr(0,right)!=strs[i].substr(0,right)){
                preright = right;
                right = (right+preleft)/2;
                break;
            }
            else {
                if (i == strs.size()-1){
                    preleft = right;
                    right = (right+preright)/2;
                }
            }
        }
    }
    pre = strs[0].substr(0,right);
    return pre;
}
int main(){
    const char* s[] = {"abab","aba","abacd"};
    vector<string> v(s,s+3);
    cout<<longestPrefix(v)<<endl;
}Python版本
def longPrefix(strs):
pre = strs[0][0]
l = len(strs)
for i in range(len(strs[0])):
for n,j in enumerate(strs):
if(i == 0):
if strs[0][i] != j[i]:
return ""
continue
if(i+1 > len(j)):
return pre
if (strs[0][i] != j[i]):
return pre
else:
if n == l-1:
# print(strs[0][i])
pre += strs[0][i]
return pre
strs = ["ad","abc","ae"]
print(longPrefix(strs))
15.三数之和
给定一个数组nums=[-1,0,1,2,-1,-4],满足要求的三元组集合[[-1,0,1],[-1,-1,2]]。
算法思想:对数组做排序后,固定一个元素后对另外两个元素采用二分法,其中关于两个元素迭代的方法有很多优化的空间,这里并没有做优化。
C++版本
vector<vector<int>> threeSum(vector<int> &nums){
    vector<vector<int>> result;
    int n = nums.size();
    if(n<3) return result;
    sort(nums.begin(),nums.end());
   
    for(int i=0;i<n-2;i++){
        if(nums[i-1]&&nums[i-1]==nums[i]) continue;
        int left=i+1;
        int right=n-1;
        while (left<right){
            if(nums[i]+nums[left]+nums[right]>0){
                right--;
            }
            else if (nums[i]+nums[left]+nums[right]<0){
                left++;
            }
            else{
                result.push_back(vector<int>{nums[i],nums[left],nums[right]});
                right--;
                left++;
            }
        }
    }
    return result;
}
void out(vector<vector<int>> &result){
    cout<<"{";
    for(int i=0;i<result.size();i++){
        cout<<"{";
        for(int j=0;j<result[i].size();j++){
            if(j==result[i].size()-1){
                cout<<result[i][j];
                
            }
            else cout<<result[i][j]<<",";
        }
        if(i==result.size()-1){
             cout<<"}";
        }
        else cout<<"},";
    }
    cout<<"}"<<endl;
}
int main(){
    vector<int> nums = {-1,0,1,2,-1,-4};
    vector<vector<int>> result;
    result = threeSum(nums);
    out(result);
    
}Python版本
class Solution(object):
def threeSum(self,nums):
nums.sort()
n = len(nums)
result = []
if len(nums)<3:
return result
for i in range(n-2):
if (nums[i-1] and nums[i]==nums[i-1]): continue
left = i+1
right = n-1
while(left<right):
sum = nums[i]+nums[left]+nums[right]
if(sum>0):
right -= 1
elif(sum<0):
left +=1
else:
result.append([nums[i],nums[left],nums[right]])
left += 1
right -= 1
return result
cla = Solution()
result = cla.threeSum([-1,0,1,2,-1,-4])
print(result)
16.最接近的三数之和
给定一个数组和目标元素,找出数组中三个元素相加最接近目标元素的情况,返回三个元素的sum。
算法思想:参考15题
C++版本
int threeSum(vector<int> &nums,int target){
    sort(nums.begin(), nums.end());
    int dis = INT_MAX;
    int result = 0;
    for(int i=0;i<nums.size()-2;i++){
        long left = i+1;
        long right = nums.size()-1;
        while (left<right) {
            int sum = nums[i] + nums[left] + nums[right];
            if(sum == target){
                dis = 0;
                return target;
            }
            else{
                if(abs(sum-target)<dis){
                    dis = abs(sum-target);
                    result = sum;
                }
                if(sum>target){
                    right--;
                }
                else{
                    left++;
                }
            }
        }
    }
    return result;
}
int main(){
    vector<int> nums = {-1,2,1,4};
    int target = 1;
    int result;
    result = threeSum(nums, target);
    cout<<result<<endl;
}Python
class Solution(object):
def threeSum(self,nums,target):
nums.sort()
dis = float("inf")
result = 0
n = len(nums)
if(n<3): return result
for i in range(n):
if(nums[i-1] and nums[i-1]==nums[i]):
continue
left = i+1
right = n-1
while(left<right):
sum = nums[i] + nums[left] + nums[right]
if(sum==target): return target
if(abs(sum-target)<dis):
result = sum
if(sum>target): right -= 1
else: left += 1
return result
cla = Solution()
print(cla.threeSum([-1,2,1,-4],1))
17.电话号码的字母组合
给定一个仅包含2-9的字符串,返回所有它能表示的字母组合。
算法思想:可以通过递归调用,Python版本采用这种方法;C++则是通过构建两个字符向量,每增加一个数字都重新刷新整个数组。
C++版本
vector<string> int2String(string ints){
    vector<vector<string>> dictory = {{"a","b","c"},{"d","e","f"},
                                {"g","h","i"},{"j","k","l"},
                                {"m","n","o"},{"p","q","r","s"},
                                {"t","u","v"},{"w","x","y","z"}};
    vector<string> result;
    vector<string> tmp;
    if(ints.size()<=0) {return tmp;}
    for(int i=0;i<ints.size();i++){
        int n = ints[i]-'0';
        if(i==0) {
            for (int j=0; j<dictory[n-2].size(); j++) {
                tmp.push_back(dictory[n-2][j]);
                result = tmp;
            }
        }
        else{
            result = {};
            for(int j=0;j<tmp.size();j++){
                for (int k=0; k<dictory[n-2].size(); k++) {
                    result.push_back(tmp[j] + dictory[n-2][k]);
                };
            }
            tmp = result;
        }
        
    }
    return result;
}
void printVector(vector<string> & ss){
    cout<<"[";
    for(int i=0;i<ss.size();i++){
        cout<<ss[i]<<",";
        if(i==ss.size()-1) cout<<"]"<<endl;
    }
}
int main(){
    string ints = "93";
    vector<string> result;
    result = int2String(ints);
    printVector(result);
}Python版本
def numCombination(ss):
d = {1:"",2:"abc",3:"def",4:"ghi",5:"jkl",6:"mno",7:"pqrs",8:"tuv",9:"wxyz"}
result = []
if(len(ss) <= 0): return result
def dfs(digits,index,path,res,d):
if index == len(digits):
res.append("".join(path))
# print(res)
return
digit = int(digits[index])
for c in d.get(digit,[]):
path.append(c)
dfs(digits,index+1,path,res,d)
path.pop()
dfs(ss,0,[],result,d)
return result
print(numCombination("23"))
18.四数之和
给定一个包含n个整数的数组nums和一个目标值target,判断nums中是否存在四个元素a,b,c和d,使得a+b+c+d的值与d相同,找出所有满足条件且不重复的四元组。
算法思想:与上面?寻找三个整数类似,固定一个元素,双指针寻找其他元素,不过四个整数需要调用三个整数。
C++版本
vector<vector<int>> threeSum(vector<int> &nums,int target){
    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(nums[i-1]&&nums[i]==nums[i-1]) continue;
        int left = i+1;
        int right = nums.size() - 1;
        while (left<right) {
            int sum;
            sum = nums[i] + nums[left] + nums[right];
            if(sum==target){
                vector<int> temp = {nums[i],nums[left],nums[right]};
                res.push_back(temp);
                left++;
                right--;
            }
            else if(sum>target){
                right--;
            }
            else{
                left++;
            }
        }
    }
    return res;
}
vector<vector<int>> fourSum(vector<int> nums,int target){
    vector<vector<int>> res;
    int n = nums.size();
    if(n<4) return res;
    sort(nums.begin(), nums.end());
    for(int i=0;i<n-3;i++){
        if(nums[i-1]&&nums[i-1]==nums[i]) continue;
        int target3 = target-nums[i];
        vector<int> num(nums.begin()+i+1,nums.end());
        vector<vector<int>> temp = threeSum(num, target3);
        for(int j=0;j<temp.size();j++){
            temp[j].insert(temp[j].begin(),nums[i]);
            res.push_back(temp[j]);
        }
    }
    return res;
}
void out(vector<vector<int>> &result){
    cout<<"{";
    for(int i=0;i<result.size();i++){
        cout<<"{";
        for(int j=0;j<result[i].size();j++){
            if(j==result[i].size()-1){
                cout<<result[i][j];
            }
            else cout<<result[i][j]<<",";
        }
        if(i==result.size()-1){
             cout<<"}";
        }
        else cout<<"},";
    }
    cout<<"}"<<endl;
}
int main(){
    vector<int> nums = {-1,0,1,2,-1,-4,3,4};
    int target = 0;
    vector<vector<int>> result;
    result = fourSum(nums,target);
    out(result);
}Python版本
def fourSum(nums,target):
"""
:param nums: [int]
:param target: int
:return: [[int]]
"""
def threeSum(nums,target):
res = []
n = len(nums)
if n<3: return res
for i in range(n-2):
if(nums[i-1] and nums[i-1]==nums[i]): continue
left = i+1
right = n-1
while(left<right):
sum = nums[i] + nums[left] + nums[right]
if(sum == target):
res.append([nums[i],nums[left],nums[right]])
left += 1
right -= 1
elif(sum>target):
right -= 1
else:
left += 1
return res
result = []
n = len(nums)
if(n<4): return result
nums.sort()
for i in range(n-3):
if(nums[i-1] and nums[i-1]==nums[i]):
continue
target3 = target - nums[i]
nums3 = nums[i+1:]
temp = threeSum(nums3,target3)
print(temp)
for t in temp:
t.append(nums[i])
result.append(t)
return result
print(fourSum([-1,0,1,2,-1,-4,3,4],0))
19.删除链表的倒数第N个节点
给定一个链表,删除链表的倒数第n个节点,并且返回链表的头结点。
算法思想:尝试通过构建相差n步的双指针来找到倒数第n+1个节点。
C++版本
struct ListNode{
    int val;
    ListNode* next;
};
ListNode *rmNthnode(ListNode *head,int n){
    if(head==NULL||n<=0) return NULL;
    ListNode *dummy = (ListNode*)malloc(sizeof(ListNode));
    dummy->val = 0;
    dummy->next = head;
    ListNode *start,*end;
    start = dummy;
    end = head;
    for(int i=0;i<n;i++) {
        end = end->next;
    }
    while (end!=NULL) {
        end = end->next;
        start = start->next;
    }
    start->next = start->next->next;
    return head;
}
void printListNode(ListNode *head){
    if(head==NULL) return;
    ListNode *tmp = head;
    while (tmp!=NULL) {
        cout<<tmp->val<<"->";
        tmp = tmp->next;
    }
    cout<<endl;
}
ListNode *createListNode(vector<int> nums){
    ListNode *head,*end,*node;
    head = (ListNode*)malloc(sizeof(ListNode));
    end = head;
    for(int i=0;i<nums.size();i++){
        node = (ListNode*)malloc(sizeof(ListNode));
        node->val = nums[i];
        end->next = node;
        end = node;
    }
    end->next = NULL;
    return head;
}
int main(){
    vector<int> nums= {1,2,3,4,5};
    ListNode *head =createListNode(nums);
    printListNode(head);
    head = rmNthnode(head, 2);
    printListNode(head);
}Python 版本
"""19.删除链表的倒数第N个节点"""
class ListNode(object):
def __init__(self,x):
self.val = x
self.next = None
class Solution(object):
def remove_nth_from_end(self,head,n):
"""
:param head: ListNode
:param n: int
:return: ListNode
"""
dummy = ListNode(-1)
dummy.next = head
start = head
end = dummy
for i in range(n):
start = start.next
while(start):
start = start.next
end = end.next
end.next = end.next.next
return head
def printListNode(self,head):
dummy = head
while(dummy):
print(dummy.val,end=",")
dummy = dummy.next
print("")
head = ListNode(-1)
a = head.next = ListNode(1)
b = a.next = ListNode(2)
c = b.next = ListNode(3)
d = c.next = ListNode(4)
e = d.next = ListNode(5)
sol = Solution()
sol.printListNode(head)
head = sol.remove_nth_from_end(head,2)
sol.printListNode(head)
20.有效的括号
给定一个只包含’(’,’)’,’[’,’]’,’{’,’}'的字符串,判断字符串是否有效。
算法思想:处理关键点在于右括号,每一个右括号都应该与最近的左括号相对应。
C++版本
bool isValid(string s){
    // map<char,char> m= {{'(',')'},{'[',']'},{{'{','}'}}};
    stack<char> st;
    for(auto ch: s){
        if(ch=='('||ch=='['||ch=='{') {
            st.push(ch);
        }
        else{
            if(st.empty()) return false;
            char ss = st.top();
            if(ss=='('&&ch!=')') return false;
            else if (ss=='['&&ch!=']') return false;
            else if (ss=='{'&&ch!='}') return false;
            st.pop();
        }
    }
    return st.empty();
}
int main(){
    string s1 = "{{}}()";
    string s2 = "[(])";
    cout<<isValid(s1)<<"--"<<isValid(s2)<<endl;
}Python 版本
def isValid(s):
"""
:param s: str
:return: bool
"""
d = {"(":")","[":"]","{":"}"}
tmp = ""
for i in s:
if i in d.keys():
tmp += i
else:
if tmp=="": return False
if d[tmp[-1]]!=i: return False
tmp = tmp[:-1]
return tmp==""
s1 = "(){}"
s2 = "[(])"
print(isValid(s1))
print(isValid(s2))
本文代码可能有bug,还请各位看官指正,或者小伙伴们有更好的算法,欢迎评论~
                
