如上图
1 无重复字符子串,主要思想是 map 记录每个字符出现的长度,一定要要求是1次。出现一个记录一个
双指针滑动窗,如果第一次出现就加上,然后于 result 比较长度,长的就覆盖 result。当遇到相同元素的时候
就进入循环 begin 前移,在移动中,把原来的元素一一在 map 里--,直到当前元素在 map 中出现次数为1
string getLongestSubstr(string ss) {
string result = "";
int begin = 0;
int right = 0;
string word = "";
int char_map[128] = {0};
for (int i=0;i<ss.size(),i++) {
char_map[ss[i]] ++;
if(char_map[ss[i]] == 1) {
word += ss[i];
if (word.size() > result.size()) {
result = word;
}
} else {
while(begin<i && char_map[ss[i]] > 1) {
char_map[char_map[begin]]--;
begin++;
}
word.assign(ss, begin,i-begin+1);
}
}
return result;
}
2 数据流中的中位数,使用大顶堆于小顶堆
float getMidNum(std::vector<int> &vec) {
priority_queue<int, std::vector<int>, greater<int>> small_heap;
priority_queue<int, std::vector<int>, less<int>> big_heap;
for(ahto i:vec) {
if(big_heap.empty()) {
big_heap.push(i);
} else {
if (big_heap.size() == small_heap.size()) {
if(small_heap.top() < i) {
small_heap.push(i);
} else{
big_heap.push(i);
}
} else if(big_heap.size() +1 == small_heap.size()) {
if (i < small_heap.top()) {
big_heap.push(i);
} else {
big_heap.push(small_heap.top());
small_heap.pop();
small_heap.push(i);
}
} else if (big_heap.size() == small_heap() +1) {
if(i > big_heap.top()) {
small_heap.push(i);
} else {
small_heap.push(big_heap.top());
big_heap.pop();
big_heap.push(i);
}
}
}
}
if (big_heap.size() == small_heap.size()) {
return (big_heap.top() + small_heap.top())>>1;
} else if (big_heap.size() > small_heap.size()) {
return big_heap.top();
} else {
return small_heap.top();
}
}
3 剪绳子 II, 求剪短的绳子剪成 k段的时候长度乘积最大,至少减为两段,主要是拆解为2,3的因子,主要是3因子居多即最大,类似于爬楼梯
int getMultiLen(int n) {
std::vector<int> res(1001,0);
res[1] = 1;
res[2] = 1;//(1*1)
res[3] = 2;//(1*2)
res[4] = 4;//(2*2)
res[5] = 6;//(2*3)
res[6] = 9;//(3*3)
//从因子7开始
for (int i = 7; i <= n; i++)
{
res[i] = res[i-3]*3;
}
return res[n];
}
4 构建乘积数组,求除去自己的数组其他元素乘积合
std::vector<int> getMultiArr(std::vector<int> &vec) {
int size = vec.size();
std::vector<int> res(size+1,0);
int left = 1;
int right = 1;
for (int i = 0; i < size; i++)
{
res[i] *= left;
left *= vec[i];
res[size-1-i] *= right;
right *= vec[size-1-i];
}
return res;
}
5 数组中出现次数超过一半的数字 ,可以用 map,可以用临时变量
int getNum(std::vector<int> &nums){
//用 map
std::map<int, int> mp;
for(auto num:nums) {
mp[num]++;
if (mp[num] > nums.size()>>1) {
return num;
}
}
//用零时变量
int cur = 1;
int res = nums[0];
for (int i = 1; i < nums.size(); i++) {
if (nums[i] == res) {
cur++;
} else {
cur--;
}
if (cur == 0) {
cur = 1;
res = nums[i];
}
}
return res;
}
6 数组中数字出现的次数 ,数组中有两个数字出现一次,其他出现两次
std::vector<int> getTwoNum(std::vector<int> &nums) {
int s = 0;
for(auto num : nums) {
s ^= num;
}
//利用 S,-S 与操作得到最后一个1的位置,两个出现一次的数字这个位置肯定不相同,否则S 就是0了
//然后利用这个位置分别与nums中元素判断将其分割成两队(1,1,3),(2,2,6);
int k = s&(-s);
std::vector<int> res;
for (auto num:nums) {
if (k&num) {
res[0] ^= num;
} else {
res[1] ^= num;
}
}
return res;
}
7 二叉树的最近公共祖先
TreeNode* getFather(TreeNode* root, TreeNode* p, TreeNode* q) {
if(!root || root == p|| root == q) {
return root;
}
TreeNode* left = getFather(root->left, p, q);
TreeNode* right = getFather(root->right, p, q);
//如果左右都有,返回根
if (left && right) {
return root;
}
return left? left:right;
}
8 二叉搜索树的后序遍历序列 ,找到最后一个根节点,然后从左边遍历第一个大于它的就是右子树起点,遍历右子树,有比他小的就 false,然后递归
bool isValidPostOrder(std::vector<int> nums) {
if (nums.empty()) {
return true;
}
return checkOrder(nums, 0, nums.size() -1);
}
bool checkOrder(std::vector<int> &nums, int start, int end) {
if (start > end) {
return true;
}
int root = nums[end];
int i=start;
for (; i < end; i++) {
if (nums[i] > root) {
//找到了右子树起点
break;
}
}
for (int j=i;j<end;j++) {
if (nums[j] < root) {
return false;
}
}
//没有的话分别遍历左右子树
bool left = checkOrder(nums, start, i - 1);
bool right = checkOrder(nums, i, end - 1);
return left&&right;
}
9 原地删除排序数组中的重复项,大神解法
int deleteSame(std::vector<int> &nums) {
int j=0;
for (int i = 1; i < nums.size(); i++) {
if (nums[j] != nums[i]) {
nums[++j] = nums[i];
}
}
return ++j;//nums.assign(0,++j);
}
10 第 k 个数(丑数)有些数的素因子只有 3,5,7,请设计一个算法找出第 k 个数。
注意,不是必须有这些素因子,而是必须不包含其他的素因子。例如,前几个数按顺序应该是 1,3,5,7,9,15,21。
int getKNum(int k) {
int i3 = 0;
int i5 = 0;
int i7 = 0;
std::vector<int> nums(1001,1);
for (int i = 1; i < k; i++) {
nums[i] = min(nums[i3]*3, min(nums[i5]*5, nums[i7]*7));
if (nums[i] == nums[i3]*3) i3++;
if (nums[i] == nums[i5]*5) i5++;
if (nums[i] == nums[i7]*7) i7++;
}
return nums[k-1];
}