auto commit
This commit is contained in:
parent
f636f9c8bf
commit
1a478a905f
|
@ -122,7 +122,7 @@ DataInputStream 装饰者提供了对更多数据类型进行输入的操作,
|
||||||
|
|
||||||
UTF-16be 中的 be 指的是 Big Endian,也就是大端。相应地也有 UTF-16le,le 指的是 Little Endian,也就是小端。
|
UTF-16be 中的 be 指的是 Big Endian,也就是大端。相应地也有 UTF-16le,le 指的是 Little Endian,也就是小端。
|
||||||
|
|
||||||
Java 的内存编码使用双字节编码 UTF-16be,这不是指 Java 只支持这一种编码方式,而是说 char 这种类型使用 UTF-16be 进行编码。char 类型占 16 位,也就是两个字节,Java 使用这种双字节编码是为了让一个中文或者一个英文都能使用一个 char 来存储。
|
Java 使用双字节编码 UTF-16be,这不是指 Java 只支持这一种编码方式,而是说 char 这种类型使用 UTF-16be 进行编码。char 类型占 16 位,也就是两个字节,Java 使用这种双字节编码是为了让一个中文或者一个英文都能使用一个 char 来存储。
|
||||||
|
|
||||||
## String 的编码方式
|
## String 的编码方式
|
||||||
|
|
||||||
|
|
|
@ -1209,19 +1209,21 @@ Class 和 java.lang.reflect 一起对反射提供了支持,java.lang.reflect
|
||||||
- **Method** :可以使用 invoke() 方法调用与 Method 对象关联的方法;
|
- **Method** :可以使用 invoke() 方法调用与 Method 对象关联的方法;
|
||||||
- **Constructor** :可以用 Constructor 创建新的对象。
|
- **Constructor** :可以用 Constructor 创建新的对象。
|
||||||
|
|
||||||
**反射的优点:**
|
**反射的优点:**
|
||||||
- **可扩展性** :应用程序可以利用全限定名创建可扩展对象的实例,来使用来自外部的用户自定义类。
|
|
||||||
- **类浏览器和可视化开发环境** :一个类浏览器需要可以枚举类的成员。可视化开发环境(如IDE)可以从利用反射中可用的类型信息中受益,以帮助程序员编写正确的代码。
|
|
||||||
- **调试器和测试工具** : 调试器需要能够检查一个类里的私有成员。测试工具可以利用反射来自动地调用类里定义的可被发现的API定义,以确保一组测试中有较高的代码覆盖率。
|
|
||||||
|
|
||||||
|
* **可扩展性** :应用程序可以利用全限定名创建可扩展对象的实例,来使用来自外部的用户自定义类。
|
||||||
|
* **类浏览器和可视化开发环境** :一个类浏览器需要可以枚举类的成员。可视化开发环境(如 IDE)可以从利用反射中可用的类型信息中受益,以帮助程序员编写正确的代码。
|
||||||
|
* **调试器和测试工具** : 调试器需要能够检查一个类里的私有成员。测试工具可以利用反射来自动地调用类里定义的可被发现的 API 定义,以确保一组测试中有较高的代码覆盖率。
|
||||||
|
|
||||||
**反射的缺点:**
|
**反射的缺点:**
|
||||||
|
|
||||||
尽管反射非常强大,但也不能滥用。如果一个功能可以不用反射完成,那么最好就不用。在我们使用反射技术时,下面几条内容应该牢记于心。
|
尽管反射非常强大,但也不能滥用。如果一个功能可以不用反射完成,那么最好就不用。在我们使用反射技术时,下面几条内容应该牢记于心。
|
||||||
|
|
||||||
- **性能开销** :反射涉及了动态类型的解析,所以JVM无法对这些代码进行优化。因此,反射操作的效率要比那些非反射操作低得多。我们应该避免在经常被执行的代码或对性能要求很高的程序中使用反射。
|
* **性能开销** :反射涉及了动态类型的解析,所以 JVM 无法对这些代码进行优化。因此,反射操作的效率要比那些非反射操作低得多。我们应该避免在经常被执行的代码或对性能要求很高的程序中使用反射。
|
||||||
- **安全限制** :使用反射技术要求程序必须在一个没有安全限制的环境中运行。如果一个程序必须在有安全限制的环境中运行,如Applet,那么这就是个问题了。
|
|
||||||
- **内部暴露** :由于反射允许代码执行一些在正常情况下不被允许的操作(比如访问私有的属性和方法),所以使用反射可能会导致意料之外的副作用,这可能导致代码功能失调并破坏可移植性。反射代码破坏了抽象性,因此当平台发生改变的时候,代码的行为就有可能也随着变化。
|
* **安全限制** :使用反射技术要求程序必须在一个没有安全限制的环境中运行。如果一个程序必须在有安全限制的环境中运行,如 Applet,那么这就是个问题了。
|
||||||
|
|
||||||
|
* **内部暴露** :由于反射允许代码执行一些在正常情况下不被允许的操作(比如访问私有的属性和方法),所以使用反射可能会导致意料之外的副作用,这可能导致代码功能失调并破坏可移植性。反射代码破坏了抽象性,因此当平台发生改变的时候,代码的行为就有可能也随着变化。
|
||||||
|
|
||||||
|
|
||||||
- [Trail: The Reflection API](https://docs.oracle.com/javase/tutorial/reflect/index.html)
|
- [Trail: The Reflection API](https://docs.oracle.com/javase/tutorial/reflect/index.html)
|
||||||
|
|
|
@ -632,7 +632,7 @@ B
|
||||||
|
|
||||||
它们都属于 Object 的一部分,而不属于 Thread。
|
它们都属于 Object 的一部分,而不属于 Thread。
|
||||||
|
|
||||||
只能用在同步方法或者同步控制块中使用,否则会在运行时抛出 IllegalMonitorStateException。
|
只能用在同步方法或者同步控制块中使用,否则会在运行时抛出 IllegalMonitorStateExeception。
|
||||||
|
|
||||||
使用 wait() 挂起期间,线程会释放锁。这是因为,如果没有释放锁,那么其它线程就无法进入对象的同步方法或者同步控制块中,那么就无法执行 notify() 或者 notifyAll() 来唤醒挂起的线程,造成死锁。
|
使用 wait() 挂起期间,线程会释放锁。这是因为,如果没有释放锁,那么其它线程就无法进入对象的同步方法或者同步控制块中,那么就无法执行 notify() 或者 notifyAll() 来唤醒挂起的线程,造成死锁。
|
||||||
|
|
||||||
|
|
|
@ -4,6 +4,3 @@
|
||||||
|
|
||||||
- [Twitter Java Style Guide](https://github.com/twitter/commons/blob/master/src/java/com/twitter/common/styleguide.md)
|
- [Twitter Java Style Guide](https://github.com/twitter/commons/blob/master/src/java/com/twitter/common/styleguide.md)
|
||||||
- [Google Java Style Guide](http://google.github.io/styleguide/javaguide.html)
|
- [Google Java Style Guide](http://google.github.io/styleguide/javaguide.html)
|
||||||
- [阿里巴巴Java开发手册](https://github.com/alibaba/p3c/blob/master/%E9%98%BF%E9%87%8C%E5%B7%B4%E5%B7%B4Java%E5%BC%80%E5%8F%91%E6%89%8B%E5%86%8C%EF%BC%88%E8%AF%A6%E5%B0%BD%E7%89%88%EF%BC%89.pdf)
|
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -2826,55 +2826,6 @@ public int LastRemaining_Solution(int n, int m) {
|
||||||
return (LastRemaining_Solution(n - 1, m) + m) % n;
|
return (LastRemaining_Solution(n - 1, m) + m) % n;
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
## 解题思路详解
|
|
||||||
创新的解法,采用数学公式推导找到规律,推导过程如下:
|
|
||||||
|
|
||||||
Step1.
|
|
||||||
首先定义一个关于 m 和 n 的函数:f(n, m),表示在n个数字 0,1,2…,n-1 中每次删除第m个数字,最后剩下的那个数字。
|
|
||||||
注意:f(n, m)表示的是,在经过了多次删除后,最后剩下的那个数字,也就是说f(n,m)本质上是个数。
|
|
||||||
|
|
||||||
Step2.
|
|
||||||
n个数中,第一个被删除的数是(m - 1) % n,把它记为k,此时数组中还剩下0,1,2… k-1, k+1,…n-1 这几个数字。接下来从k+1开始计数,相当于在剩下的序列中,k+1排在最前面,从而形成k+1,… n-1,… 0,1,2…k-1。本题中,第一个被删除的是数字2,因此数组还剩下 0,1,3,4,5,相当于3,4,5,0,1。由于这个序列是不连续的,在2那个地方断开了,所以不能写为f(n-1, m)。在此记为g(n-1, m)。
|
|
||||||
最初序列最后剩下的数字,一定是删除一个数字后剩下的数字,因此f(n, m) = g(n-1, m)
|
|
||||||
|
|
||||||
Step3.
|
|
||||||
将[3,4,5,0,1]重新映射为[0,1,2,3,4],映射的公式是:p(x) = (x - k - 1) % n。其中k = 2,n = 6。
|
|
||||||
3 —-> 0
|
|
||||||
4 —-> 1
|
|
||||||
5 —-> 2
|
|
||||||
0 —-> 3
|
|
||||||
1 —-> 4
|
|
||||||
映射以后的序列是0,1,2,3,4,是一个连续的序列,因此可以用f(n-1, m)来表示。
|
|
||||||
此时的f(n-1, m)是不等于g(n-1, m),因为二者对应的序列不同,存在一个映射关系。
|
|
||||||
该映射的逆映射是 p’(x) = (x + k + 1) % n
|
|
||||||
因此g(n-1, m) = p’[f(n-1, m)] = [f(n-1, m) + k + 1] % n
|
|
||||||
即:f(n, m) = [f(n-1, m) + k + 1] % n
|
|
||||||
带入k = (m - 1) % n, 得到f(n, m) = [f(n-1, m) +m] % n (n > 1)
|
|
||||||
|
|
||||||
Step4.
|
|
||||||
当n = 1时,只有一个人,此时剩余的数字为0
|
|
||||||
|
|
||||||
综上,约瑟夫环的公式是:
|
|
||||||
f(n, m) = 0 (n = 1)
|
|
||||||
f(n, m) = [f(n-1, m) +m] % n (n > 1)
|
|
||||||
|
|
||||||
```java
|
|
||||||
public class Solution {
|
|
||||||
|
|
||||||
public int LastRemaining_Solution(int n, int m) {
|
|
||||||
// 不合法输入的判断
|
|
||||||
if(n == 0 || m < 1) {
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
int last = 0;
|
|
||||||
for(int i = 2; i <= n; i++) {
|
|
||||||
last = (last + m) % i;
|
|
||||||
}
|
|
||||||
return last;
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
# 63. 股票的最大利润
|
# 63. 股票的最大利润
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue
Block a user