图书馆存包柜两人交替占用的改进:
问题:目前图书馆存放柜取包后一定时间内不可继续存包(防止占用)。于是出现了,两个人轮流存放占柜的现象。下面从2个角度解决这一问题。
- 1 如果记录使用者的信息,每个用户记录上次存放的柜子序号,刷卡后,30分钟内不允许存包,30分钟后不允许存放于上一次使用的柜子。
- 2 如果记录存放柜的信息,那么每个柜子以队列形式保留最近2次~3次的用户,在队列上的用户不可以存放该柜子。
- 3 改进:每个用户记录上次存放的存放柜所在组,刷卡后,30分钟内不允许存包,30分钟后不允许存放于上一次使用的那组。图书馆目前共6组,每组包含很多储柜。这样效果更好,可以补上之前的一个漏洞。
整型有无符号(unsigned)和有符号(signed)两种类型,无符号的均表正数。有符号的二进制第一位为1代表负数,第一位为0代表正数。
正数按正常二进制表示,负数存储时遵从以下规则:原码的补码(即原码的反码加1)。
在默认情况下声明的整型变量都是有符号的类型,如果需声明无符号类型的话就需要在类型前加上unsigned。
同样的数据长度,无符号和有符号的区别就是无符号类型能保存2倍于有符号类型的数据,比如16位系统中一个有符号整型能存储的数据的范围为 -32768 ~ 32767,而unsigned整形能存储的数据范围则是0 ~ 65535。
JVM规范:
Integral Types and ValuesThe values of the integral types are integers in the following ranges:
For byte, from -128 to 127, inclusive
For short, from -32768 to 32767, inclusive
For int, from -2147483648 to 2147483647, inclusive
For long, from -9223372036854775808 to 9223372036854775807, inclusive
For char, from ‘\u0000’ to ‘\uffff’ inclusive, that is, from 0 to 65535,char类型是无符号的。
LHS=left hand side 等式左边
RHS=right hand side 等式右边
s.t 数学such that,运筹学subject to
iff= if and only if
i.e. (id est,拉丁) 即,也就是
e.g. (拉丁短语exempli gratia) 例如
cf. (confer (=compare) ,拉丁)比较,或 查阅
int[][] myArray = new int[3][];
myArray[0] = new int[5];
myArray[1] = new int[15];
myArray[2] = new int[3];
myArray[1][10];
myArray[2][10]: Array index out of bounds.
eclipse 程序计时:
long startTime = System.currentTimeMillis(); //获取开始时间
doSomething(); //测试的代码段
long endTime = System.currentTimeMillis(); //获取结束时间
System.out.println(“程序运行时间:” + (endTime - startTime) + “ms”); //输出程序运行时间
第二种是以纳秒为单位计算的。
long startTime=System.nanoTime(); //获取开始时间
doSomeThing(); //测试的代码段
long endTime=System.nanoTime(); //获取结束时间
System.out.println("程序运行时间: "+(endTime-startTime)+“ns”);
public class Main {
public static void main(String[] args) {
//自动装箱
Integer total = 99;
//自定拆箱
int totalprim = total;
}
}
latex除法:$\frac{a}{b}$,得到
a
b
\frac{a}{b}
ba
markdown居中:<center>,如
公式居中:$$ f(x) $$,如
x
2
x^2
x2
赋值符号“=”在对象、对象变量间的赋值操作时,应该理解为:引用,指向,对象变量的指针发生改变,重新指向(引用、管理)新的对象。在一些节点的remove、insert等操作,其实就是改变特定对象变量的指针,在Java中就是改变特定对象变量的引用。
子类可以通过super关键字调用父类的构造函数。
一个类的构造函数的第一行可以通过this关键字来调用自己的其他构造函数。
this 和super在构造函数中只能有一个,且都必须是构造函数当中的第一行。
java的位运算符中有一个叫异或的运算符,用符号 ^ 表示,位的异或运算 ^:
运算规则是:两个数转为二进制,然后从高位开始比较,如果 相同则为0,不相同则为1。如:
- 5 ^3 = 101 ^ 011 = 110=6;
- 5 ^4,实为 101 ^100,得到001即10进制的1;
- 5 ^5 = 0。
- 5 ^(-3) = - 8;5 ^(-4)= - 7;5 ^(-5)= - 2。
注意正数在Java中的编码就是二进制,其中首位是0表示符号,负数首位符号位是1(也即正数和0的首位都是0),且十进制的负数的二进制编码是其①绝对值②的反码③再加1,即
5就是0 0……0101,-3就是(①0011→②1100→)③1 1……1101,5 ^(-3)=1 1……1000,那么,逆运算转为十进制(③1 1……1 1000→②1 1……1 0111→①00……0 1000)即绝对值为8的负数,即-8。
System.out.println(Integer.toBinaryString(5));
System.out.println(Integer.toBinaryString(-3));
System.out.println(Integer.toBinaryString(-8));
101
11111111111111111111111111111101
11111111111111111111111111111000
有了上面的异或运算符后,那么判断两整数异号还是同号就可以用异或来判断,两数异号则异或运算必小于0,同号则大于等于0,但注意任何数与0的异或得到的还是数本身,因此我们需额外要求(判断)数不等于0。
public int sign(int a, int b) {
int result = 0;
if (a != 0 && b != 0) {
if ((a ^ b) < 0) {
result = -1;
} else {
result = 1;
} // of inner if-else
} // of if
return result;
} // of sign
验证:
System.out.println(sign(4,-3)); // -1
System.out.println(sign(3,4)); // 1
System.out.println(sign(5,0)); // 0
“/”和“Math.floorDiv”
java中 int数的除法 / : a,b ∈ \in ∈Z, a / b = a/b= a/b=sign ( a b ) ⋅ ⌊ ∣ a / b ∣ ⌋ (ab)·\lfloor |a/b| \rfloor (ab)⋅⌊∣a/b∣⌋,即 4 / 4 = 1 4/4=1 4/4=1, 3 / 4 = 0 3/4=0 3/4=0, ( − 3 ) / 4 = 0 (-3)/4=0 (−3)/4=0, ( − 5 ) / 4 = − 1 (-5)/4=-1 (−5)/4=−1。这里的sign(int)就是x>0取1、x=0取0、x<0取-1的符号函数,不是前面判断2整数异号关系的sign(int int)。
Math.floorDiv(a,b) =
⌊
a
/
b
⌋
\lfloor a/b \rfloor
⌊a/b⌋,如:
Math.floorDiv(4,4) = 1,Math.floorDiv(3,4) = 0,Math.floorDiv(-3,4) = -1,Math.floorDiv(-5,4) = -2。
求余“%”和求模“floorMod”
java中的求余运算 %:a,b ∈ \in ∈Z, a % b = a − a\%b=a - a%b=a−sign ( a b ) ⋅ ⌊ ∣ a / b ∣ ⌋ × b (ab)·\lfloor |a/b| \rfloor\times b (ab)⋅⌊∣a/b∣⌋×b,在java中就是
a%b == a - a/b*b
如:
5
%
3
=
5
%
(
−
3
)
=
2
5\%3=5\%(-3)=2
5%3=5%(−3)=2,
(
−
5
)
%
3
=
(
−
5
)
%
(
−
3
)
=
−
2
(-5)\%3=(-5)\%(-3)=-2
(−5)%3=(−5)%(−3)=−2。
求模运算 Math.floorMod(a,b) =
a
−
⌊
a
/
b
⌋
×
b
a - \lfloor a/b \rfloor\times b
a−⌊a/b⌋×b,如:
Math.floorMod(5, 3) = 2,Math.floorMod(5, -3) = -1,Math.floorMod(-5, 3) = 1,Math.floorMod(-5, -3) = -2。
可以看到,当两整数同号时(sign(ab)=1和|a/b|=a/b),二者是相同的。
当异号时,若余数为0(则
a
/
b
=
⌊
∣
a
/
b
∣
⌋
a/b=\lfloor |a/b| \rfloor
a/b=⌊∣a/b∣⌋),则二者依然相等都为0;若二者异号且余数不为0,则
⌊
a
/
b
⌋
=
−
⌊
∣
a
/
b
∣
⌋
−
1
\lfloor a/b \rfloor=-\lfloor |a/b| \rfloor-1
⌊a/b⌋=−⌊∣a/b∣⌋−1,如
⌊
−
11
/
4
⌋
=
−
3
=
−
⌊
11
/
4
⌋
−
1
\lfloor -11/4 \rfloor=-3=-\lfloor 11/4 \rfloor-1
⌊−11/4⌋=−3=−⌊11/4⌋−1,
进一步可得:
Math.floorMod(a,b) =
a
−
⌊
a
/
b
⌋
×
b
=
a
+
(
⌊
∣
a
/
b
∣
⌋
+
1
)
×
b
=
(
a
+
⌊
∣
a
/
b
∣
⌋
×
b
)
+
b
=
a
%
b
+
b
a - \lfloor a/b \rfloor\times b=a +(\lfloor |a/b| \rfloor+1)\times b=(a +\lfloor |a/b| \rfloor\times b)+b=a\%b+b
a−⌊a/b⌋×b=a+(⌊∣a/b∣⌋+1)×b=(a+⌊∣a/b∣⌋×b)+b=a%b+b
吐槽:LaTeX的公式输入真的慢!!!
下面是源码中Math.floorMod(int, int)的说明:
Returns the floor modulus of the arguments. The floor modulus is {@code a - (floorDiv(a, b) * b)}, has the same sign as the divisor {@code b}, and is in the range of {@code -abs(y) < r < +abs(y)}.
ublic static int floorMod(int x, int y) {
int mod = x % y;
// if the signs are different and modulo not zero, adjust result
if ((mod ^ y) < 0 && mod != 0) {
mod += y;
}
return mod;
}
If the signs of the arguments are the same, the results of {@code floorMod} and the {@code %} operator are the same.
floorMod(+4, +3) == +1; and +4 % +3 == +1
floorMod(-4, -3) == -1; and -4 % -3 == -1
If the signs of the arguments are different, the results differ from the {@code %} operator.
floorMod(+4, -3) == -2; and +4 % -3 == +1
floorMod(-4, +3) == +2; and -4 % +3 == -1
注意mod例程是较为耗时的,前面指出
a
%
b
=
a
−
a\%b=a -
a%b=a−sign
(
a
b
)
⋅
⌊
∣
a
/
b
∣
⌋
×
b
(ab)·\lfloor |a/b| \rfloor\times b
(ab)⋅⌊∣a/b∣⌋×b
Math.floorMod(a,b) =
a
−
⌊
a
/
b
⌋
×
b
a - \lfloor a/b \rfloor\times b
a−⌊a/b⌋×b
其中,Math.floorMod(a,b) 是基于
a
%
b
a\%b
a%b == a - a/b* b 计算的,因此模运算尽量转换为求余运算:a - a/b*b,%运算本身也是较为复杂的运算(2次乘法1次加法),算法设计时慎重。
String是字符串,是一连串的字符,其中的空格也是字符,如字符串"a + b"有5个字符。
String有个java.lang.String.charAt(int index) 方法,Returns the char value at the specified index. An index ranges from 0 to length() - 1。
i ‘\0’ 代表空的字符,!=0 !=null !=’ ’
">>" 和 "<<"
“m >> n”,m和n是两个int,表示
⌊
m
/
2
n
⌋
\lfloor m/2^n \rfloor
⌊m/2n⌋
“m << n”,m和n是两个int,表示
m
×
2
n
m\times2^n
m×2n
其中,LaTeX中向下取整和向上取整为:
$\lfloor x \rfloor$
$\lceil x \rceil$
System.out.println(" " + (16 >> 2) + " " + (15 >> 2) + " " + (14 >> 2) + " " + (13 >> 2) + " " + (12 >> 2)
+ " " + (11 >> 2) + " " + (10 >> 2) + " " + (9 >> 2) + " " + (8 >> 2) + " " + (7 >> 2) + " "
+ (6 >> 2) + " " + (5 >> 2) + " " + (4 >> 2) + " " + (3 >> 2) + " " + (2 >> 2) + " " + (1 >> 2)
+ " " + (0 >> 2));
System.out.println((-16 >> 2) + " " + (-15 >> 2) + " " + (-14 >> 2) + " " + (-13 >> 2) + " " + (-12 >> 2) + " "
+ (-11 >> 2) + " " + (-10 >> 2) + " " + (-9 >> 2) + " " + (-8 >> 2) + " " + (-7 >> 2) + " " + (-6 >> 2)
+ " " + (-5 >> 2) + " " + (-4 >> 2) + " " + (-3 >> 2) + " " + (-2 >> 2) + " " + (-1 >> 2));
结果:
4 3 3 3 3 2 2 2 2 1 1 1 1 0 0 0 0
-4 -4 -4 -4 -3 -3 -3 -3 -2 -2 -2 -2 -1 -1 -1 -1
"i++" 和 "++i"
i++ 即后加加,原理是:先自增,然后返回自增之前的值;
++i 即前加加,原理是:先自增,然后返回自增之后的值。
i即不论是前++还是后++,都有个共同点是先自增。