leetcode刷题(第一周)

(一)栈的基本应用
1)括号匹配
输入只含有()[]{}的字符串,判断是否属于合法表达式
示例输入:"{[()]}"
输出:true
思路:选用栈容器,字符串元素以此入栈判断,若最后栈为空,则合法。
class Solution{
public:
bool isValid(string s)
{stack V;
int i=0;
int j=s.size()-1;
char p;
while(i<=j)
{switch(s[i])
{case ‘(’:
case ‘[’:
case ‘{’:V.push(s[i]);
i++;
break;
case ‘)’: if(V.empty())
return false;
else p=V.top();
V.pop();
if(p!=’(’)
return false;
else {i++;
break;}
case ‘]’:
if(V.empty())
return false;
else p=V.top();
V.pop();
if(p!=’[’)
return false;
else {i++;
break;}
case ‘}’:
if(V.empty())
return false;
else p=V.top();
V.pop();
if(p!=’{’)
return false;
else {i++;
break;}
}
}if(V.empty())
return true;
else return false;
}
};

2)最小栈的实现
进行Min操作,将返回栈内此时的最小值
示例输入:[“push”,“push”,“push”,“pop”,“Min”]
[“2”,“3”,“1”,"",""]
输出:["","","",“1”,“2”]
使用辅助栈,栈顶与此时操作栈中的最小值保持同步,Min操作返回辅助栈栈顶元素
class MinStack {
private: stack s1;
stack s2;
public:
void push(int x) {
s1.push(x);
if(s2.empty()||x<=getMin()) s2.push(x);
else s2.push(getMin());
}
void pop() {
int x=s1.top();
s1.pop();
s2.pop();
}
int top() {
return s1.top();
}
int getMin() {
return s2.top();
}
};

3)行星碰撞
我们得到了一组整数的小行星,它们代表一排的小行星。对于每个小行星,绝对值代表其大小,符号代表其方向(正意味着右,负意味着左)。每颗小行星都以相同的速度移动。找出所有碰撞后小行星的状态。如果两颗小行星相遇,较小的一颗会爆炸。如果两者大小相同,都会爆炸。两颗朝同一方向移动的小行星永远不会相遇。
示例输入:[10,2,-5]
输出:[10]
思路:通过栈容器,对每个数组元素进栈进行符号及绝对值判断,直至数组末尾,最后输出栈中元素即可。
class Solution {
private: stack v;
public:
int judgesign(int a,int b)//a is the stack’s top
{int tag=0;
if((a>0&&b>0)||(a<0&&b<0))
tag=0;
else if(a>0&&b<0)
tag=1;
else if(a<0&&b>0)
tag=-1;
return tag;
}
vector asteroidCollision(vector& asteroids) {
vector res;
int i=0;
int p=0;
while(i<asteroids.size())
{if(v.empty())
{v.push(asteroids[i]);
++i;}
else {p=v.top();
if(judgesign(p,asteroids[i])0||judgesign(p,asteroids[i])-1)
{v.push(asteroids[i]);
++i;}
else if(judgesign(p,asteroids[i])1)
{if(p>0-asteroids[i])
++i;
else if(p
0-asteroids[i])
{v.pop();
++i;}
else if(p<0-asteroids[i])
v.pop();
} //end elseif }
}//end while
while(!v.empty())
{res.push_back(v.top());
v.pop();
}
reverse(res.begin(),res.end());
return res;
}
};

(二)数组相关练习
1)字符串排序
给定一int数组,将其组合排为最大的数,并以string形式输出
示例输入:[“30”,“285”,“75”,“9”]
输出:“97530285”
思路:通过sort排序,将compare函数表示为两个字符串之间的大小比较,再将排序后的数组以string输出
class Solution {
public:
static bool compare(int a,int b)//字符串比较函数
{string s1= to_string(a);
string s2= to_string(b);
return s1+s2>s2+s1;
}
string largestNumber(vector& nums) {
sort(nums.begin(),nums.end(),compare);
string res="";
for(int i=0;i<nums.size();++i)
{string temp= to_string(nums[i]);
res+=temp;
}
int pos=0;
for(pos;pos<res.size();++pos)//防止数组头部的"0"字符
if(res[pos]!=‘0’)
break;
if(posres.size())
res=‘0’;
return res;
}
};
2)寻找最长回文字符串
给定一字符串,返回其中最长的回文字符串
示例输入:“abebdc”
输出:“beb”
起初刚开始的思路是暴力解法,顺序遍历,保留最长长度与起始位置,最后输出,但时间复杂度过大。
class Solution {
public:
bool isPalindromic(string s,int begin,int end)//judge the string is palindromic
{int i=begin; int j=end;
while(i<j)
{if(s[i]!=s[j])
return false;
else {i++;
j–;}
} return true; }
string longestPalindrome(string s) {
int longb=0;
int longe=0;
int i=0;
int maxlen=1;
int j;
while(i(s.size()/2)&&i>=s.size()/2)
break;
while(!isPalindromic(s,i,j))
j–;
if(j-i+1>maxlen&&i<=j)
{maxlen=j-i+1;
longb=i;
longe=j;
i++;}
else i++;
}
return s.substr(longb,longe-longb+1);
}
};
看了讨论区的一些思路后,发现可以从中间向两边扩展寻找回文字符串,并且跳过中间所有重复的字符(必定回文),这样遍历时间复杂度低,效率更快。
class Solution {
public:
string longestPalindrome(string s) {
if (s.size()0) return “”;
if (s.size() == 1) return s;
int longb = 0, maxlen = 1;
for (int i = 0; i < s.size()? {
if (s.size() - i <= maxlen / 2) break;
int j = i, k = i;
while (k < s.size()-1 && s[k+1] == s[k]) ++k; //跳过所有重复字符
i = k+1;
while (k 0 && s[k + 1] == s[j - 1])
{ ++k; --j; }
int len = k - j + 1;
if (len >= maxlen) { longb = j; maxlen = len; }
}
return s.substr(longb, max_len);
}
};
3)最小子数组和
给定一个n个正整数和一个正整数的数组,求其元素和≥s的连续子数组的最小长度。如果没有,则返回0。
示例输入:s=7,nums=[2,3,1,2,4,3]
输出:2
思路:从0开始遍历数组,找到第一个大于等于s的元素位置pos,因其是正整数数组,故只需从pos位置之后进行遍历(pos之前位置和必定小于s),直至数组末尾,时间复杂度O(n)
class Solution {
public:
int minSubArrayLen(int s, vector& nums) {
int minlen=nums.size()+1;
int i=0;
int k=0;
int res=0;
bool tag=0;//标志位,标明一次遍历是否可以找到满足条件的数组
if(nums.size()0) return 0;
while(i<nums.size()-1)
{ tag=0;
while(k<nums.size())
{if(res=s)
{tag=1;
if(minlen>k-i)
minlen=k-i;}
if(!tag) return (minlen
nums.size()+1)?0:minlen;
res-=nums[i];
++i; }
return minlen;} };
4)快乐数
写一个算法来确定一个数字是否“快乐”。快乐数是由以下过程定义的一个数字:从任意正整数开始,用数字的平方和替换数字,然后重复这个过程,直到数字等于1(在这里它将保持不变),或者在不包含1的循环中无限循环。这个过程以1结尾的数字是快乐数字。
示例输入:19
输出:true
思路:这道题关键是怎么判断已经循环,刚开始我想到的是用map,再看了讨论区后,发现也可以用判断一个单链表是否存在环的方式,时间复杂度大体相同。
class Solution {
public:
int digitsq(int n)//n的各位平方和
{int res=0;
while(n!=0)
{res+=pow(n%10,2);
n/=10; }
return res;
}
bool isHappy(int n) {
int fast=n;
int low=n;
do { low=digitsq(low);//仿照判断链表循环中的快、慢指针
fast=digitsq(fast);
fast=digitsq(fast);
} while(low!=fast);
if(low
1)
return true;
else return false;
/* map<int,int> m;//map实现判断循环
if(n
1) return true;
while(n!=1)
{if(m[n]!=1)
m[n]=1;
else return false;
n=digitsq(n);
}
return true;*/
}
};
5)查找排序数组中元素的第一个和最后一个位置
给定整数数组nums按升序排序,找到给定目标值的起始和结束位置。如果在数组中找不到目标,则返回[-1,-1]。
示例输入:[2,3,5,8,8,10]
输出:[3,4]
思路:设置两个变量同时从数组末尾分别遍历,直至两变量相遇或始末位置同时不等于初值,返回位置。
class Solution {
public:
vector searchRange(vector& nums, int target) {
int begin=-1;
int end=-1;
int i=0;
int j=nums.size()-1;
while(i<=j)
{if(nums[i]!=target) i++;
else begin=i;
if(nums[j]!=target)
j–;
else end=j;
if(begin!=-1&&end!=-1)
break;
}
return {begin,end};
}
};
6)两数和
给定一个整数数组,返回两个数字的索引,使它们加起来成为一个特定的目标。
可以假定每个输入只有一个解决方案,并且不能使用同一个元素两次。
示例输入:nums=[2,7,11,15], target=9
输出:[0,1]
思路:首先记录初始元素所在位置,使用sort将数组排序,设置两个变量分别从首尾部分遍历,直至两数和等于目标值,此时返回两数原始位置即可。
class Solution {
public:
int FindPos(vector &v,int x,int begin)//找到x值除begin
位置以外的位置,防止重复数字
{int i;
for(i=0;i<v.size();i++)
if(v[i]==x&&i!=begin)
break;
return i ;
}
vector twoSum(vector& nums, int target) {
vector res(2);
int len=nums.size();
vector tab(len);//tab作为地址存放数组
for(int temp=0;temp<nums.size();temp++)
tab[temp]=nums[temp];
sort(nums.begin(),nums.end());
int k=0;
int j=nums.size()-1;
while(nums[k]+nums[j]!=target)
{if(nums[k]+nums[j]>target)
j-=1;
else
k+=1; }
res[0]=FindPos(tab,nums[k],-1);
res[1]=FindPos(tab,nums[j],res[0]);
return res;
}
};

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值