import java.util.HashMap;
public class ReceiveAndPrintOrderList {
public static class Node{
public String info;
public Node next;
public Node(String str){
info = str;
}
}
public static class MessageBox{
//连续区间的开头和结尾
private HashMap<Integer,Node> headMap;
private HashMap<Integer,Node> tailMap;
//等待几号信息
private int waitPoint;
public MessageBox(){
headMap = new HashMap<>();
tailMap = new HashMap<>();
waitPoint = 1;
}
/**
*
* @param num 接受信息的编号
* @param info 接受信息的内容
*/
public void receive(int num,String info){
if(num < 1){ //所有的编号从1开始
return;
}
//封装一个节点
Node cur = new Node(info);
headMap.put(num,cur);
tailMap.put(num,cur);
//之前有没有num—1结尾的
if(tailMap.containsKey(num-1)){
tailMap.get(num-1).next = cur;
tailMap.remove(num-1);
headMap.remove(num);
}
//动手画图就明白了
if(headMap.containsKey(num+1)){
cur.next = headMap.get(num+1);
headMap.remove(num+1);
tailMap.remove(num);
}
if(num == waitPoint){
print();
}
}
private void print(){
Node node = headMap.get(waitPoint);
//去除打印的开头和结尾
headMap.remove(waitPoint);
while(node != null){
System.out.println(node.info+" ");
node = node.next;
waitPoint++;
}
tailMap.remove(waitPoint-1);
System.out.println();
}
public class MoneyWays {
public static int moneyWays(int[] aribitary,int[] onlyone,int money){
if(money < 0){
return 0;
}
if((aribitary == null) || aribitary.length == 0)&&(onlyone==null||onlyone.length == 0)){
return money == 0 ? 1 : 0;
}
int[][] dparb = getDpArb(aribitary,money);
int[][] dpone = getDpOne(onlyone,money);
if(dparb == null){
return dpone[dpone.length][money];
}
if(dpone == null){
return dpone[dparb.length][money];
}
int res = 0;
for (int i = 0; i < money; i++) {
res += dparb[dparb.length-1][i]*dpone[dpone.length-1][money-i];
}
return res;
}
//选择面值 可以重复选择
public static int[][] getDpArb(int[] arr,int money){
if(arr == null || arr.length == 0){
return null;
}
int[][] dp = new int[arr.length][money+1];
for (int i = 0; i < arr.length; i++) {
dp[i][0] = 1;
}
for(int j = 1;arr[0] * j <= money;j++){
dp[0][arr[0] * j] = 1;
}
for(int i = 1; i < arr.length;i++){
for(int j = 1;j <= money;j++){
dp[i][j] = dp[i-1][j];
dp[i][j] += j - arr[i] >= 0 ?dp[i][j-arr[i]]:0;
}
}
return dp;
}
public static int[][] getDpOne(int[] arr,int money) {
if (arr == null || arr.length == 0) {
return null;
}
int[][] dp = new int[arr.length][money + 1];
for (int i = 0; i < arr.length; i++) {
dp[i][0] = 1;
}
for (int j = 1; arr[0] * j <= money; j++) {
dp[0][arr[0] * j] = 1;
}
//我自己改的 不知道对不 理论上对
for (int i = 1; i < arr.length; i++) {
for (int j = 1; j <= money; j++) {
dp[i][j] = dp[i - 1][j];
dp[i][j] = j - arr[i] >= 0 ? dp[i][j - arr[i]] : 0;
}
}
return dp;
}
}
数位dp模型
转非递归形式
比如N=3625 f(n)为数字为n有多少个1,f(3625) = f(625)+{626到3625),f(625)依次往下分解
如果最高位是1,最高位1的数量是N%(10^(k-1))+1 一共k位
剩下的位数为1的总和是 (k-1)*(10^(k-2))
最高位不是1的情况
比如730~5729
(1)730~1729
(2)1730~2729
(3)2730~3729
(4)3730~4729
总共1的数量是
1
0
k
−
2
∗
a
∗
(
k
−
1
)
+
1
0
k
−
1
(
加
上
的
10
的
k
−
1
次
方
是
最
高
位
为
1
的
情
况
10^{k-2}*a*(k-1)+10^{k-1}(加上的10的k-1次方是最高位为1的情况
10k−2∗a∗(k−1)+10k−1(加上的10的k−1次方是最高位为1的情况
上述算法针对的是一个区间,因为是区间递归下一个区间
时间复杂度log10(N)*log10(N)
不常考5%的小概率常考的
public class OneNumber {
public static int solution2(int num){
if(num < 1){
return 0;
}
//求num的位数 代价log10N
int len = genLenOfNum(num);
if(len == 1){
return 1;
}
//num 88998989
//tmp1 10000000
int tmp1 = powerBaseOf10(len-1);
//num最高位
int first = num / tmp1;
//最高位是1 N%tmp1+1
//最高位first tmp1
int firstOneNumber = first == 1 ? num % tmp1 + 1:tmp1;
//除最高位之外 剩下1的数量
//最高位1 10(k-2次方)*(k-1) * 1
//最高位first 10(k-2次方)*(k-1)*first
int otherOneNumber = first * (len-1) * (tmp1/10);
return firstOneNumber + otherOneNumber + solution2(num % tmp1);
}
public static int genLenOfNum(int num){
int len = 0;
while(num != 0){
len++;
num /= 10;
}
return len;
}
public static int powerBaseOf10(int base){
return (int)Math.pow(10,base);
}
}