可以先对一些简单情形进行手工模拟,查找规律
有时先对数组进行排序可以使运算变得简单,提高效率
字符串问题、括号匹配问题,可以考虑逆向思维,从右往左看
从初态到某一状态A最少需要几步?可以考虑从状态A回到初态的逆过程需要几步
括号匹配,标准匹配正负之和count为0,允许一次交换则count下限调整为-1.
排列组合,组合数,排列数
数字的奇偶性
数的质因数分解
数的进制(解决称药片问题)
链表判环:快慢指针。链表相交:首尾交错相连,p、q走到相遇为止。
装箱问题,将货物按重量从大到小排序,每次尝试放最大的,放不下就开一个新的箱子。
动态规划需要找到递推式,即状态从i转移到j的公式(状态也可能是二维的(i1,j1)->(i2,j2))
动态规划时,dp数组中存储的不一定是题目的要求,可以是“以每个位置结尾这种思维方式”
动态规划:换钱的最少货币数(p191),换钱的方法数(程序员代码面试指南p196,扩展:每种货币最多拿一次的情况),0/1背包,完全背包,装箱问题
找钱的可能数(组合):每种钱币0到无穷个,钱币升序排列,for j=1,n:{dp[i] = dp[i] + dp[i-k]};0~1个,钱币降序排列,for j=n,1{dp[i] = dp[i] + dp[i-k]}
走楼梯的方法数(排列):迭代法
https://blog.csdn.net/qq_26399665/article/details/79831490
打擂台。1.如果擂台上没人,新人成为擂主。2.同一组人上台,擂主战斗力+1。3.不同组的人上台挑战,擂主战斗力-1。4.最后留在台上的是中位数。
作者:Nestler
来源:CSDN
原文:https://blog.csdn.net/nestler/article/details/25882261?utm_source=copy
实现partial_sort的思想是:对原始容器内区间为[first, middle)的元素执行make_heap()操作构造一个最大堆,然后拿[middle, last)中的每个元素和first进行比较,first内的元素为堆内的最大值。如果小于该最大值,则互换元素位置,并对[first, middle)内的元素进行调整,使其保持最大堆序。比较完之后在对[first, middle)内的元素做一次对排序sort_heap()操作,使其按增序排列。注意,堆序和增序是不同的。
时间复杂度:O(nlogk)=建堆O(k)+剩余n-k个元素插入堆中O(nlogk)+对堆内元素进行堆排序O(klogk)
https://www.cnblogs.com/algorithmic/p/3657623.html
https://blog.csdn.net/lecepin/article/details/50791404 (扩展)
详见:https://www.cnblogs.com/wangkundentisy/p/8810077.html
#include
using namespace std;
// arr[]为数组,start、end分别为数组第一个元素和最后一个元素的索引
// povitIndex为数组中任意选中的数的索引
int partition(int arr[], int start, int end)
{
int pivot = arr[end];
int storeIndex = start;
//这个循环比一般的写法简洁高效,呵呵维基百科上看到的
for(int i = start; i < end; ++i) {
if(arr[i] < pivot) {
swap(arr[i], arr[storeIndex]);
++storeIndex;
}
}
swap(arr[storeIndex], arr[end]);
return storeIndex;
}
int findkth(int arr[],int start, int end,int k){
int pivot_index = partition(arr,start,end);
if(pivot_index < k){
return findkth(arr,pivot_index+1,end,k);
}
else if(pivot_index > k){
return findkth(arr,start,pivot_index-1,k);
}
else{
return arr[pivot_index];
}
}
double findmid(int arr[],int len){
if(len%2==1){
return findkth(arr,0,len-1,(len-1)/2);
}
else{
cout<<"even"<
用findkth实现
两个栈实现队列。A栈用于入队列,B栈用于出队列,若B为空,则将A中的所有元素倒入B,再出队列。
两个队列实现栈。如果“栈”非空,则必有一队列非空。如果“栈”空,则
最大值栈:用一个max栈来同步存储可能的最大值在栈顶位置。入栈:max(当前最大值(即栈顶元素),新元素)。出栈:照常。
最大值队列(滑动窗口最大值):用一个max队列来同步存储可能的最大值在队列头位置。入队列:将max队列尾部比新元素小的元素依次出队列,然后新元素入队列。
出队列:如果出队列的索引值和max队列索引值相同,则出队列。
2-5-3-4
-5--4
(剑指offer都有的,可以去看看)
线段树or树形数组(树形分区),累加子分区的排名
http://www.cnblogs.com/weidagang2046/archive/2012/03/01/massive-user-ranking.html
1:战力排行榜,几乎实时得找出前100的玩家。(最大堆 和 计数排序),不知道有没有修改和查询都是O(1)得算法?树形数组。
a. 一直维持一个size为100的最小堆,外加一个hashmap(存储玩家ID到节点的映射)。
保存堆顶(第100名的战力)的值,其余玩家在更新积分时,如果超过了该值,插入堆(替换堆顶元素,下沉到合适位置)
b. 战力分布集中在某个区间,例如0~200,那么可以用计数排序的思想。使用数组来存储各个战力的玩家,数组的每个元素是一个链表。外加一个hashmap(存储玩家ID到节点的映射)
c. 战力分布很分散。将b中的数组换成链表,链表的每个节点是一个链表。外加一个hashmap(存储玩家ID到节点的映射)。
每次更新战力,只需要沿着链表前后找相邻战力链表,放置到战力链表中合适的位置或者新开一个链表。