数组:
1、给定一个长度为 n 的数组,其中包含范围为 1 到 n 的整数,有些整数重复了多次,有些整数 没有出现,求 1 到 n 中没有出现过的整数。
vector<int> findDisappearedNumbers(vector<int>&nums){
vector<int>ans;
for(const int &num:nums){
int pos=abs(num)-1;
if(nums[pos]>0){
nums[pos]=-nums[pos] ;
}
}
for(int i=0;i<nums.size();i++){
if(nums[i]>0){
ans.push_back(i+1);
}
}
return ans;
}
2、给定一个 n × n 的矩阵,求它顺时针旋转 90 度的结果,且必须在原矩阵上修改(in-place)。 怎样能够尽量不创建额外储存空间呢?
void rotate(vector<vector<int>>& matrix) {
int temp = 0, n = matrix.size()-1;
for (int i = 0; i <= n / 2; ++i) {
for (int j = i; j < n - i; ++j) {
temp = matrix[j][n-i];
matrix[j][n-i] = matrix[i][j];
matrix[i][j] = matrix[n-j][i];
matrix[n-j][i] = matrix[n-i][n-j];
matrix[n-i][n-j] = temp;
}
}
}
3、给定一个二维矩阵,已知每行和每列都是增序的,尝试设计一个快速搜索一个数字是否在矩 阵中存在的算法。
bool searchMatrix(vector<vector<int>>& matrix,int target){
int m=matrix.size();
if(m==0) return false;
int n=matrix[0].size();
int i=0,j=n-1;
while(i<m&&j>=0){
if(matrix[i][j]==target){
return true;
}
if(matrix[i][j]>target){
--j;
}
else{
++i;
}
}
return false;
}
4、给定一个含有 0 到 n 整数的数组,每个整数只出现一次,求这个数组最多可以分割成多少个 子数组,使得对每个子数组进行增序排序后,原数组也是增序的。
void maxChunksToSorted(vector<int>&arr){
int chunks=0,cur_max=0;
for(int i=0;i<arr.size();i++){
cur_max=max(cur_max,arr[i]);
if(cur_max==i){
++chunks;
}
}
return chunks;
}
栈和队列:
1、尝试使用栈(stack)来实现队列(queue)。
Class MyQueue{
stack<int> in,out;
public:
MyQueue(){}
void push(int x){
in.push(x);
}
int pop (){
in2out();
int x=out.top();
out.pop();
return x;
}
int peek(){
in2out();
return out.top();
}
void in2out(){
if(out.empty()){
while(!in.emppty()){
int x=in.top();
in.pop();
out.push(x);
}
}
{
bool empty(){
return in.empty()&&out.empty();
}
};
2、设计一个最小栈,除了需要支持常规栈的操作外,还需要支持在 O(1) 时间内查询栈内最小 值的功能。
Class MinStack{
stack<int> s,min_s;
public:
MinStack(){}
void push(int x){
s.push(x);
if(min_s.empty()||min_s.top()<=x){
min_s.push(x);
}
}
void pop(){
if(!min_s.empty()&& min_s.top()==s.top()){
min_s.pop();
}
s.pop();
}
int top(){
return s.top();
}
int getMin(){
return min_s.top();
}
}
3、给定一个只由左右原括号、花括号和方括号组成的字符串,求这个字符串是否合法。合法的 定义是每一个类型的左括号都有一个右括号一一对应,且括号内的字符串也满足此要求。
bool isValid(String s){
stack<char> parsed;
for (int i = 0; i < s.length(); ++i) {
if (s[i] == ’{’ || s[i] == ’[’ || s[i] == ’(’) {
parsed.push(s[i]);
} else {
if (parsed.empty()) {
return false;
}
char c = parsed.top();
if((s[i]=='}'&& c == '{'||(s[i] == ’]’ && c == ’[’) ||(s[i] == ’)’ && c == ’(’)){
parsed.pop();
else{
return false;}
}
}
}
return parseed.empty();
}
单调栈
1、给定每天的温度,求对于每一天需要等几天才可以等到更暖和的一天。如果该天之后不存在 更暖和的天气,则记为 0。
vector<int>dailyTamperatures(vector<int>&temperatures){
int n=temperatures.size();
vector<int> ans(n);
stack<int> indices;
for(int i=0;i<n;++i){
while(!indices.empty()){
int pre_index=indices.top();
if(temoeratures[i]<=temperatures[pre_index]){
break;
}
indices.pop();
ans[pre_inddex]=i-pre_index;
}
indices.push(i);
}
return ans;
}
优先队列
优先队列可以在O(1)时间内获得最大值,并且可以在O(logn)时间内取出最大值或插入任意值。
优先队列通常用堆来实现。堆是一个完全二叉树,其每个节点的值总是大于等于子节点的值。实现堆时,我们通常用一个数组而不是指针建立一个树,这是因为堆时完全二叉树,所以用数组表示时,位置i的节点的父节点位置一定为i/2,而它的两个子节点的位置又一定分别为2i和2i+1.
1、实现一个优先队列:
vector<int> heap;
void top(){
return heap[0];
}
void push(int k){
heap.push_back(k);
swim(heap.size()-1);
}
void pop(){
heap[0]=heap.back();
head.pop_back();
sink(0);
}
void swim(int pos){
while (pos > 1 && heap[pos/2] < heap[pos])) {
swap(heap[pos/2], heap[pos]);
pos /= 2;
}
void sink(int pos) {
while (2 * pos <= N) {
int i = 2 * pos;
if (i < N && heap[i] < heap[i+1]) ++i;
if (heap[pos] >= heap[i]) break;
swap(heap[pos], heap[i]);
pos = i;
}
}
2、给定 k 个增序的链表,试将它们合并成一条增序链表。
struct Comp{
bool operator()(ListNode*l1,ListNode*l2){
return l1-val > l2-> val;
}
ListNode* merageKLists(vector<ListNode*>& lists){
if(lists.empty()) return nullptr;
priortiy_queue<ListNode*,vector<ListNode*>,Comp>q;
for(ListNode* list:lists){
if(list){
q.push(list);
}
}
ListNode* dummy =new ListNode(0) ,*cur=dummy;
while(!q.empty()){
cuur->next=q.top();
q.pop();
cur=cur->next;
if(cur->next){
q.push(cur->next)
}
}
return dummy->next;
}