一、括号序列
给出一个仅包含字符'(',')','{','}','['和']',的字符串,判断给出的字符串是否是合法的括号序列
括号必须以正确的顺序关闭,"()"和"()[]{}"都是合法的括号序列,但"(]"和"([)]"不合法。
//用栈解决
class Solution {
public:
/**
*
* @param s string字符串
* @return bool布尔型
*/
bool isValid(string s) {
// write code here
stack<char>st;
int len=s.length();
for(int i=0;i<len;i++)
{
if(s[i]=='(')
st.push(')');
else if(s[i]=='[')
st.push(']');
else if(s[i]=='{')
st.push('}');
else if(st.empty())
return false;
else if(st.top()!=s[i])
return false;
else
st.pop();
}
return st.empty();
}
};
stack<char> c;
for(int i=0;i<s.length();i++)
{
if(c.empty())
{
c.push(s[i]);
continue;
}
if(s[i]==')'&&c.top()=='(') c.pop();
else if(s[i]==']'&&c.top()=='[') c.pop();
else if(s[i]=='}'&&c.top()=='{') c.pop();
else c.push(s[i]);
}
return c.empty();
二、斐波那契数列
大家都知道斐波那契数列,现在要求输入一个整数n,请你输出斐波那契数列的第n项(从0开始,第0项为0,第1项是1)。
n\leq 39n≤39
一开始肯定想到是递归,但是递归在应对比较大的数时比较慢,有较多的重复计算。
class Solution {
public:
int Fibonacci(int n) {
int a=0,b=1,c;
if(n==0) return 0;
if(n==1) return 1;
for(int i=0;i<n-1;i++)
{
c=a+b;
a=b;
b=c;
}
return c;
}
};
//时间复杂度:O(n)
//空间复杂度:O(1)
//完美!
int f = 0, g = 1;
while(n--) {
g += f;
f = g - f;
}
return f;
方法一:递归
题目分析,斐波那契数列公式为:f[n] = f[n-1] + f[n-2], 初始值f[0]=0, f[1]=1,目标求f[n]
int Fibonacci(int n) {
if (n==0 || n==1) return n;
return Fibonacci(n-1) + Fibonacci(n-2);
}
优点,代码简单好写,缺点:慢,会超时
时间复杂度:O(2^n)
空间复杂度:递归栈的空间
方法二 动态规划
时间复杂度:O(n)
空间复杂度:O(n)
int Fibonacci(int n) {
vector<int> dp(n+1, 0);
dp[1] = 1;
for (int i=2; i<=n; ++i) {
dp[i] = dp[i-1] + dp[i-2];
}
return dp[n];
}
三、二分查找
请实现有重复数字的升序数组的二分查找
给定一个 元素有序的(升序)整型数组 nums 和一个目标值 target ,写一个函数搜索 nums 中的 target,如果目标值存在返回下标,否则返回 -1
class Solution {
public:
/**
* 代码中的类名、方法名、参数名已经指定,请勿修改,直接返回方法规定的值即可
*
* 如果目标值存在返回下标,否则返回 -1
* @param nums int整型vector
* @param target int整型
* @return int整型
*/
int search(vector<int>& nums, int target) {
// write code here
int l=0,r=nums.size()-1;
int mid;
if(nums.size()==0) return -1;
while(l<=r)
{
// int mid=l+(r-l)/2;
mid=(r+l)/2;
if(nums[mid]==target)
{
while(nums[mid-1]==nums[mid])
mid--;
return mid;
}
else if(nums[mid]<target) l=mid+1;
else if(nums[mid]>target) r=mid-1;
}
return -1;
}
};
注意初始,如果数组为0,返回-1,注意找左区间第一个符合的。需要循环判断一下。
找到字符串最长无重复字符串
给定一个数组arr,返回arr的最长无的重复子串的长度(无重复指的是所有数字都不相同)。
class Solution {
public:
/**
*
* @param arr int整型vector the array
* @return int整型
*/
int maxLength(vector<int>& arr) {
// write code here
set<int>s;
int max=0,sum=0;
int l=0,r=0,n=arr.size();
while(r<n)
{
if(!s.count(arr[r]))
{
s.insert(arr[r]);
r++;
}
else
{
s.erase(arr[l]);
l++;
}
max=max>s.size()?max:s.size();
}
return max;
}
};
得考虑双指针法,哈希
寻找最长的无重复子串。
考虑以一个位置结尾的可以往前延伸到的位置,根据此位置求出无重复子串的长度。
具体操作可以记录一个指针,这个指针记录到当前位置时,可以往前延伸的最前的位置。
考虑如何更新指针,从一个位置到下一个位置时,加入了一个数a:
- 如果a在前面没有出现过,指针不变,并记下这个数。
- 如果a出现过,那么指针的位置要大于a上次出现的位置,即now=max(now,last[a]);
所以定义一个map,时刻更新每个数字上次出现的位置即可。
class Solution {
public:
int maxLength(vector<int>& arr) {
map<int,int> last;
int ans = 0, now = 0;
for (int i = 0; i < (int)arr.size(); ++i) last[arr[i]] = -1;
for (int i = 0; i < (int)arr.size(); ++i) {
if (last[arr[i]] != -1) now = max(now, last[arr[i]] + 1);
ans = max(ans, i - now + 1);
last[arr[i]] = i;
}
return ans;
}
};