1.如果有64个元素(不重复),那么有多少子集? 全部打印且不能占用额外的内存空间。
做法:有2^64种情况。不能占用额外空间的话,深搜和广搜都不可以,一个调用栈和使用队列都需要额外的内存空间。因此可以考虑二进制的做法,64位刚好是long int。
class Solution {
public:
void permunation(vector<int> nums) {
int n = nums.size();
vector<vector<int>> res;
for (long i = 0; i < (1<<n); i++) { //1<<n,将1左移n位,就是2^n
vector<int> tmp;
for (int j = 0; j < n; j++) {
if ((i & (1 << j))!= 0) //注意要加两层括号,!=的优先级高于&
tmp.push_back( nums[j]); //1向左移j位
}
res.push_back(tmp);
}
}
};
2.随机洗牌程序,空间复杂度O(1)。
class Solution {
public:
void shuffle(vector<int> nums) {
int n = nums.size();
srand((int)time(0));
for (int i = n - 1; i >= 0;i--) {
int j = rand() % (i + 1);
swap(nums[i], nums[j]);
}
}
};
3.最长不重复子串
这个题可以这样思考:ABCDBACEF这样的字符串,当我们知道位置5和位置2的B重复之后,得到了ABCD这样一个最长串,那么在位置5的B之前不会有更长的字符串了,要找只能从上一个重复的B(即位置2的B)之后开始找新的串。
使用两个指针left和right,记录最长串的左右两端,形成一个有效坐标的区间(使用这种方法是避免重置左端的时候还要擦除map中的记录)。如果新找的字符在map中有记录且它最近出现的一次也在有效区间,说明重复了。
class Solution {
public:
int lengthOfLongestSubstring(string s) {
if (s.length() <= 1) return s.length();
//记录字符和其最后一次出现的位置
unordered_map<char, int> record;
int left = 0;
int right = 1;
int res = 0;
record.insert(make_pair(s[left], left));
while (right<s.length()) {
//如果字符之前出现过且在有效区间内,说明重复了
if (record.find(s[right]) != record.end() && record[s[right]] >= left) {
res = max(res, right - left);
left = record[s[right]] + 1;
record[s[right]] = right;
}
else {
//如果字符之前出现过但没在有效区间,则不影响,已经是无用位置了。但需要更新一下最新位置。
if (record.find(s[right]) != record.end()) record[s[right]] = right;
//直接没出现过,记下来。
else record.insert(make_pair(s[right], right));
}
right++;
}
return max(res,right-left); //处理最长不重复子串在最后一段的情况
}
};
4.有()[]{}三种括号组成的序列,判断序列内的括号是否全部匹配
class Solution {
public:
bool isValidParentheses(string &s) {
stack<char> res;
for (int i=0;i<s.length();i++)
{
if (s[i]=='('||s[i]=='['||s[i]=='{') res.push(s[i]);
else
{
if (res.empty()) return false; //有右括号没有左括号的情况
char tmp=res.top();
res.pop();
if (s[i]==')'&&tmp!='(') return false; //匹配不正确的情况
if (s[i]==']'&&tmp!='[') return false;
if (s[i]=='}'&&tmp!='{') return false;
}
}
if (!res.empty()) return false;//有左括号多余的情况
return true;
}
};
5.follow up求出最长的有效括号序列
题目类似longest-valid-parentheses,这个题是只考虑一种括号的情况,可以用栈和动态规划两种算法。
class Solution {
public:
int longestValidParentheses(string s) {
if (s.length()<=1) return 0;
stack<int> left_index;
int start=0;
int res=0;
for (int i=0;i<s.length();i++) {
if (s[i]=='(') {
left_index.push(i);
continue;
} else if (left_index.empty()) {start=i+1; continue;} //形不成更长的有效括号序列了,重置start找新的
else {
left_index.pop();
if (left_index.empty()) res=max(res,i-start+1);//找到最长的 如 (()(()))从头到尾
else res=max(res,i-left_index.top());//找到局部最长的,如(()(())) 第2,3个括号是局部最长
}
}
return res;
}
};
class Solution {
public:
int longestValidParentheses(string s) {
if (s.length() <= 1) return 0;
int res = 0;
vector<int> dp(s.length(), 0);
for (int i = s.length() - 2; i >= 0; i--) {
if (s[i] == '(' && s[i+1 + dp[i+1]] == ')') {
dp[i] = dp[i+1] + 2; //扩展局部最长有序括号
if (i+1 + dp[i+1] + 1<s.length() && dp[i+1+dp[i+1]+1]>0)
dp[i] = dp[i] + dp[i+1 + dp[i+1] + 1];//连接后面有可能出现的其他括号
}
res = max(res, dp[i]);
}
return res;
}
};
只要多加一个判断括号种类是否一致即可。
6.升序数列找target
34. Find First and Last Position of Element in Sorted Array
一定要问清楚要求,比如特殊情况如何返回等!!!
class Solution {
public:
vector<int> searchRange(vector<int>& nums, int target) {
if (nums.size()<=0) return vector<int>(2,-1);
int i=0;
int j=nums.size()-1;
while (i+1<j) {
int mid=(j-i)/2+i;
if (nums[mid]>=target) j=mid;
else i=mid+1;
}
vector<int> res;
if (nums[i]!=target && nums[j]==target) i=j;
if (nums[i]==target ) {
res.push_back(i);
int tmp=i;
while (i+1<nums.size() && nums[i+1]==target) i++;
res.push_back(i);
}else
{
res.push_back(-1);
res.push_back(-1);
}
return res;
}
};
7.股票买卖问题
https://blog.youkuaiyun.com/musechipin/article/details/88841590
8.0-1背包
https://blog.youkuaiyun.com/musechipin/article/details/88623481
9.判断一个数是否为对称树
https://blog.youkuaiyun.com/musechipin/article/details/85005947