给定一个N行3列二维数组,每一行表示有一座大楼,一共有N座 大楼。 所有大楼的底部都坐落在X轴上,每一行
的三个值 (a,b,c)代表每座大楼的从(a,0)点开始,到 (b,0)点结束,高 度为c。 输入的数据可以保证a<b,且
a,b,c均为正数。大楼之 间可以有重合。 请输出整体的轮廓线。 例子:给定一个二维数组 [ [1, 3, 3], [2,
4, 4], [5, 6, 1] ]
输出为轮廓线[ [1,2,3], [2,4,4], [5,6,1]]
//
// main.cpp
// AdvancedFour
//
// Created by 吴珝君 on 2019/5/22.
// Copyright © 2019年 闲着也是贤者. All rights reserved.
//
/*
水平面上有 N 座大楼,每座大楼都是矩阵的形状,可以用一个三元组表示 (start, end, height),分别代
表其在x轴上的起点,终点和高度。大楼之间从远处看可能会重叠,求出 N 座大楼的外轮廓线。
外轮廓线的表示方法为若干三元组,每个三元组包含三个数字 (start, end, height),代表这段轮廓的起始
位置,终止位置和高度。
[[1, 3, 3], [2, 4, 4], [5, 6, 1]]
[[1, 2, 3],[2, 4, 4],[5, 6, 1] ]
*/
#include <iostream>
#include <vector>
#include <map>
#include <algorithm>
using namespace std;
class Position{
public:
Position(bool isup, int x, int hight)
{
this->isup = isup;
this->x = x;
this->hight = hight;
}
bool isup;
int x;
int hight;
};
class Building{
public:
Building(int start, int end, int hight)
{
this->start = start;
this->end = end;
this->hight = hight;
}
int start;
int end;
int hight;
};
bool comp(Position o1, Position o2)
{
if (o1.x != o2.x) {
return o1.x < o2.x;
}
if (o1.isup != o2.isup) {
if (o1.isup) {
return true;
}
return false;
}
return false;
}
class DealDate
{
public:
vector<vector<int>> getOutline(vector<Building> vb)
{
vector<vector<int>> res;
map<int , int> htmap;
map<int, int> maxmap;
vector<Position> v = getPosition(vb);
sort(v.begin(), v.end(), comp);
for (int i = 0; i < v.size(); i++) {
if(v[i].isup)
{
if (htmap.count(v[i].hight) == 0)
{
htmap[v[i].hight] = 1;
}
else
{
htmap[v[i].hight]++;
}
}
else
{
if(htmap.find(v[i].hight)->second>=1)//遍历
{
if (htmap.find(v[i].hight)->second == 1)
{
htmap.erase(v[i].hight);
}
else
{
htmap[v[i].hight]--;
}//
}
}
if (htmap.empty()) {
maxmap[v[i].x] =0;
}
else
{
maxmap[v[i].x] = htmap.rbegin()->first;
}
}
int h =0;
int start = 0;
map<int, int>::iterator it ;
for ( it = maxmap.begin(); it != maxmap.end(); it++) {
int hcur = it->second;
cout << hcur <<endl;
if (h != hcur)
{
if (h !=0)
{
vector<int> v;
v.push_back(start);
v.push_back(it->first);
v.push_back(h);
res.push_back(v);
}
start = it->first;
h = hcur;
}
}
return res;
}
private:
vector<Position> getPosition(vector<Building> vb)
{
vector<Position> v;
for (int i = 0; i < vb.size(); i++) {
v.push_back(Position( true,vb[i].start,vb[i].hight));
v.push_back(Position(false, vb[i].end,vb[i].hight));
}
return v;
}
};
设计可以变更的缓存结构(LRU) 【题目】
设计一种缓存结构,该结构在构造时确定大小,假设大小为K,并有两个功能: set(key,value):将记录
(key,value)插入该结构。 get(key):返回key对应的value值。
【要求】
1.set和get方法的时间复杂度为O(1)。 2.某个key的set或get操作一旦发生,认为这个key的记录成了最经常使
用的。
3.当缓存的大小超过K时,移除最不经常使用的记录,即set或get最久远的。
【举例】
假设缓存结构的实例是cache,大小为3,并依次发生如下行为: 1.cache.set("A",1)。最经常使用的记录为
("A",1)。 2.cache.set("B",2)。最经常使用的记录为("B",2),("A",1)变为最不经常的。
3.cache.set("C",3)。最经常使用的记录为("C",2),("A",1)还是最不经常的。 4.cache.get("A")。最经常
使用的记录为("A",1),("B",2)变为最不经常的。 5.cache.set("D",4)。大小超过了3,所以移除此时最不经
常使用的记录("B",2), 加入记录 ("D",4),并且为最经常使用的记录,然后("C",2)变为最不经常使用的 记录
typedef struct double_link_list
{
int key;
int val;
struct double_link_list *pre;
struct double_link_list *next;
double_link_list(int key, int val)
{
this->key = key;
this->val = val;
this->pre = NULL;
this->next = NULL;
}
} Linklist;
class LRUCache {
public:
/*
* @param capacity: An integer
*/LRUCache(int capacity) {
// do intialization if necessary
this->capacity = capacity;
head = NULL;
tail = NULL;
}
/*
* @param key: An integer
* @return: An integer
*/
int get(int key) {
// write your code here
if (umlist.count(key)) {
int t = umlist.find(key)->second->val;
set(key, t);
return t;
}
else
return -1;
}
/*
* @param key: An integer
* @param value: An integer
* @return: nothing
*/
void set(int key, int value) {
// write your code here
if (umlist.count(key) == 1) {
Linklist *cur = umlist.find(key)->second;
if (head == cur && (cursize >1)) {//是头节点并且当前节点数目大于1
head = head->next;
head->pre = NULL;
tail->next = cur;
cur->pre = tail ;
tail = tail->next;
tail->next = NULL;
}
else if((cur != tail )&& (head != cur))//不是头和尾
{
Linklist *p = cur->pre;
Linklist *n = cur->next;
p->next = n;
n->pre = p;
tail ->next = cur;
cur->pre = tail;
tail = tail->next;
tail->next = NULL;
}//如果只有一个元素或者是尾部元素
cur->val = value;
}
else
{
if (cursize == capacity)
{
//找到要删除的值
umlist.erase(head->key);
Linklist *l = head;
head = head->next;
delete l;
l =NULL;
cursize--;
}
Linklist *node = new Linklist(key,value);
if (head == NULL)
{
head = node;
tail = node;
}
else
{
tail ->next = node;
node->pre = tail;
tail = tail->next;
}
umlist.insert(pair<int, Linklist*>(key,node));
cursize++;
}
}
private:
int capacity;
int cursize = 0;
Linklist *head;
Linklist *tail;
unordered_map<int,Linklist*> umlist;//存key node
};
class Node
{
public:
int key;
int val;
Node(int key, int val)
{
this->key = key;
this->val = val;
}
};
class LRUCache {
public:
/*
* @param capacity: An integer
*/LRUCache(int capacity) {
// do intialization if necessary
this->capacity = capacity;
}
/*
* @param key: An integer
* @return: An integer
*/
int get(int key)
{
// write your code here
if (umlist.count(key)) {
int t = umlist.find(key)->second->val;
set(key,t);
return t;
}
return -1;
}
/*
* @param key: An integer
* @param value: An integer
* @return: nothing
*/
void set(int key, int value) {
// write your code here
if (umlist.count(key) == 1) {
//删除当前位置节点,并增加到尾部
Node *node = umlist.find(key)->second;
list<Node*>::iterator it = find(l.begin(), l.end(), node);//找到当前节点位置
l.erase(it);
node->val = value;
l.push_back(node);
}
else
{
if (l.size() == capacity)
{
umlist.erase(l.front()->key);
l.pop_front();
}
Node *node = new Node(key, value);
l.push_back(node);
umlist.insert(pair<int,Node* >(key, node));
}
}
private:
int capacity;
list<Node*> l;
unordered_map<int,Node*> umlist;//存key node
};
#include <list>
using namespace std;
class Node
{
public:
int key;
int val;
Node( int key,int val)
{
this->key = key;
this->val = val;
}
};
class LRUCache {
public:
/*
* @param capacity: An integer
*/LRUCache(int capacity) {
// do intialization if necessary
this->capacity = capacity;
}
/*
* @param key: An integer
* @return: An integer
*/
int get(int key)
{
// write your code here
if (umlist.count(key)) {
int ret = (*(umlist.find(key)->second))->val;
set(key, ret);
return ret;
}
return -1;
}
/*
* @param key: An integer
* @param value: An integer
* @return: nothing
*/
void set(int key, int value) {
// write your code here
if (umlist.count(key)) {
list<Node*>::iterator it = umlist.find(key)->second;
Node *node = *it;
node->val = value;
l.erase(it++);
l.push_back(node);
umlist[key] = (--l.end());
// umlist.insert(pair<int, list<Node*>::iterator >(key, --l.end()));
/*
需要先删除再操作
*/
}
else
{
if (l.size() == capacity)
{
umlist.erase(l.front()->key);
l.pop_front();
}
Node *node = new Node(key, value);
l.push_back(node);
//umlist.insert(pair<int, list<Node*>::iterator >(key, --l.end()));
umlist[key] = (--l.end());
}
}
private:
int capacity;
list<Node*> l;
unordered_map<int,list<Node*> ::iterator > umlist;//存key node
};
上一题实现了LRU缓存算法,LFU也是一个著名的缓存算法 自行了解之后实现LFU中的set 和 get 要求:两个方法
的时间复杂度都为O(1)
给定一个数组arr,和一个整数num,求在arr中,累加和等于num的最长 子数组的长度
例子:
arr = {7,3,2,1,1,7,7,7} num = 7 其中有很多的子数组累加和等于7,但是最长的子数组是{3,2,1,1},所
以返回其长度4
/*
求和为aim值的最长子数组
*/
/*
算法的思路,就是找到计算从第一个数组到某个子数组的和,每计算一个,就减去目标值,计算当前的结果数组中,
有没有对应的sum,如果有的话,获取这个值得坐标位置,没有则什么都不做。
*/
class Solution
{
public:
vector<int> getChildArr(vector<int> arr, int aim)
{
vector<int> res;
int sum = 0;
map<int,int> m;//sum + 坐标
m.insert(pair<int, int>(0, -1));//一个值也没放的时候坐标是-1 sum =0
int start =-1;//起始下标也是-1
int end = -1;//终止下标也是-1
for (int i = 0; i < arr.size(); i++) {
sum+=arr[i];
if (m.count(sum -aim) ==1)
{
if(end -start <( i - m.find(sum - aim)->second))
{
start = m.find(sum - aim)->second;
end = i;
}
}
else
{
m.insert(pair<int, int>(sum, i));//只会保存最先出现的i值
}
}
for (int i = start; i <end; i++) {
res.push_back(arr[i+1]);
}
return res;
}
};
定义数组的异或和的概念: 数组中所有的数异或起来,得到的结果叫做数组的异或和, 比如数组{3,2,1}的异或
和是,3^2^1 = 0
给定一个数组arr,你可以任意把arr分成很多不相容的子数组,你的目的是: 分出来的子数组中,异或和为0的子
数组最多。
请返回:分出来的子数组中,异或和为0的子数组最多是多少?
class Solution
{
public:
int mostEor(vector<int> arr)
{
if(arr.size() == 0)
return 0;
int xors =0;
map<int, int> m;
int dp[1000] = {0};
if (arr[0] == 0)
{
dp[0] = 1;
}
m.insert(pair<int, int>(arr[0],0));
m[xors] = arr[0];
for (int i = 1; i < arr.size(); i++)
{
xors ^=arr[i];
if (m.count(xors))//如果遇到相同的时候异或和一定是0
{
int l = dp[m.find(xors)->second] +1;
int r = dp[i - 1];
dp[i] = (l > r ? l : r);
}
else
{
dp[i] = dp[i - 1];
}
m[xors] = i;
}
return dp[arr.size()-1];
}
};
给定一棵二叉树的头节点head,请返回最大搜索二叉子树的大小
//
// main.cpp
// maxBST
//
// Created by 吴珝君 on 2019/5/29.
// Copyright © 2019年 闲着也是贤者. All rights reserved.
//
#include <iostream>
#include <string.h>
class TreeNode {
public:
int val;
TreeNode *left, *right;
TreeNode(int val) {
this->val = val;
this->left = this->right = NULL;
}
};
class retData
{
public:
retData(int s, TreeNode *current, int max, int min)
{
this->size = s;
this->head = current;
this->max = max;//左子树最大值节点
this->min = min;//右子树最小值节点
}
int size;//返回当前所在子树的最大搜索子树节点个数
TreeNode *head;//最大搜索二叉树的头
int max;
int min;//当前子树的最大值与最小值
};
#include <algorithm>
using namespace std;
class Solution
{
public:
retData maxBST(TreeNode *root)
{
if(root == NULL)
{
return retData(0,NULL,-65535,65535);//当该节点为空的时候的处理,最大值赋值为最小,最小值赋值为最大,来避免对后序比较的影响
}
TreeNode *left = root->left;
TreeNode *right = root->right;
retData l = maxBST(left);
retData r = maxBST(right);
int includeroot = 0;
int maxs = 0;
int mins = 0;
TreeNode * curNode = NULL;
if (l.head == left && r.head == right
&&l.max < root->val && r.min > root->val )
{
includeroot = l.size + r.size + 1;
}
//其他情况都是在子树中找最大的
int maxpath = max(includeroot,max( l.size, r.size));//当前子树的最大节点个数
//求当前节点位置的最大二叉搜索子树
curNode = (l.size > r.size ? l.head : r.head);
if (maxpath == includeroot) {
curNode = root;
}//当前最大子树的根节点
maxs = max(max(l.max,r.max),root->val);//当前子树最大节点
mins = min(min(l.min, r.min), root->val);//当前子树最小节点
return retData(maxpath, curNode, maxs,mins);
}
};
//
void inorder(TreeNode *root)
{
if (root == NULL) {
return;
}
inorder(root->left);
cout << root->val<<endl;
inorder(root->right);
}
int main(int argc, const char * argv[]) {
// insert code here...
std::cout << "Hello, World!\n";
TreeNode *r = new TreeNode(15);
r->left = new TreeNode(14);
r->left->left = new TreeNode (100);
r->left->left->left = new TreeNode (90);
r->left->left->right = new TreeNode (101);
r->right = new TreeNode(20);
r->right->left = new TreeNode(19);
r->right->right = new TreeNode(21);
Solution s;
retData rt = s.maxBST(r);
inorder(rt.head);
cout << rt.size <<endl;
return 0;
}
给定一个数组arr,和一个整数num,求在arr中,累加和等于num的最长 子数组的长度
例子:
arr = {7,3,2,1,1,7,7,7} num = 7 其中有很多的子数组累加和等于7,但是最长的子数组是{3,2,1,1},所 以返回其长度4
求和为aim值的最长子数组
*/
/*
算法的思路,就是找到计算从第一个数组到某个子数组的和,每计算一个,就减去目标值,计算当前的结果数组中,
有没有对应的sum,如果有的话,获取这个值得坐标位置,没有则什么都不做。
*/
class Solution
{
public:
vector<int> getChildArr(vector<int> arr, int aim)
{
vector<int> res;
int sum = 0;
map<int,int> m;//sum + 坐标
m.insert(pair<int, int>(0, -1));//一个值也没放的时候坐标是-1 sum =0
int start =-1;//起始下标也是-1
int end = -1;//终止下标也是-1
for (int i = 0; i < arr.size(); i++) {
sum+=arr[i];
if (m.count(sum -aim) ==1)
{
if(end -start <( i - m.find(sum - aim)->second))
{
start = m.find(sum - aim)->second;
end = i;
}
}
else
{
m.insert(pair<int, int>(sum, i));//只会保存最先出现的i值
}
}
for (int i = start; i <end; i++) {
res.push_back(arr[i+1]);
}
return res;
}
};