文章目录
- 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,还请各位看官指正,或者小伙伴们有更好的算法,欢迎评论~