auto commit

This commit is contained in:
CyC2018 2018-06-26 17:25:44 +08:00
parent 45d251eda3
commit 89aefa963b
2 changed files with 98 additions and 61 deletions

View File

@ -35,17 +35,21 @@ Java 的 I/O 大概可以分成以下几类:
# 二、磁盘操作 # 二、磁盘操作
File 类可以用于表示文件和目录,但是它只用于表示文件的信息,而不表示文件的内容。 File 类可以用于表示文件和目录的信息,但是它不表示文件的内容。
递归地输出一个目录下所有文件: 递归地输出一个目录下所有文件:
```java ```java
public static void listAllFiles(File dir) { public static void listAllFiles(File dir)
{
if (dir == null || !dir.exists()) {
return;
}
if (dir.isFile()) { if (dir.isFile()) {
System.out.println(dir.getName()); System.out.println(dir.getName());
return; return;
} }
for (File file : dir.listFiles()) { for (File file : Objects.requireNonNull(dir.listFiles())) {
listAllFiles(file); listAllFiles(file);
} }
} }
@ -56,12 +60,13 @@ public static void listAllFiles(File dir) {
使用字节流操作进行文件复制: 使用字节流操作进行文件复制:
```java ```java
public static void copyFile(String src, String dist) throws IOException { public static void copyFile(String src, String dist) throws IOException
FileInputStream in = new FileInputStream("file/1.txt"); {
FileOutputStream out = new FileOutputStream("file/2.txt"); FileInputStream in = new FileInputStream(src);
FileOutputStream out = new FileOutputStream(dist);
byte[] buffer = new byte[20 * 1024]; byte[] buffer = new byte[20 * 1024];
// read() 最多读取 buffer.length 个字节,返回的是实际读取的个数 /* read() 最多读取 buffer.length 个字节
// 返回 -1 的时候表示读到 eof即文件尾 返回的是实际读取的个数,返回 -1 的时候表示读到 eof即文件尾 */
while (in.read(buffer, 0, buffer.length) != -1) { while (in.read(buffer, 0, buffer.length) != -1) {
out.write(buffer); out.write(buffer);
} }
@ -87,7 +92,8 @@ DataInputStream 装饰者提供了对更多数据类型进行输入的操作,
不管是磁盘还是网络传输,最小的存储单元都是字节,而不是字符。但是在程序中操作的通常是字符形式的数据,因此需要提供对字符进行操作的方法。 不管是磁盘还是网络传输,最小的存储单元都是字节,而不是字符。但是在程序中操作的通常是字符形式的数据,因此需要提供对字符进行操作的方法。
InputStreamReader 实现从文本文件的字节流解码成字符流OutputStreamWriter 实现字符流编码成为文本文件的字节流。 - InputStreamReader 实现从文本文件的字节流解码成字符流;
- OutputStreamWriter 实现字符流编码成为文本文件的字节流。
逐行输出文本文件的内容: 逐行输出文本文件的内容:
@ -98,8 +104,9 @@ String line;
while ((line = bufferedReader.readLine()) != null) { while ((line = bufferedReader.readLine()) != null) {
System.out.println(line); System.out.println(line);
} }
// 装饰者模式使得 BufferedReader 组合了一个 Reader 对象 /* 装饰者模式使得 BufferedReader 组合了一个 Reader 对象
// 在调用 BufferedReader 的 close() 方法时会去调用 fileReader 的 close() 方法,因此只要一个 close() 调用即可 在调用 BufferedReader 的 close() 方法时会去调用 fileReader 的 close() 方法
因此只要一个 close() 调用即可 */
bufferedReader.close(); bufferedReader.close();
``` ```
@ -140,31 +147,35 @@ byte[] bytes = str1.getBytes();
序列化的类需要实现 Serializable 接口,它只是一个标准,没有任何方法需要实现,但是如果不去实现它的话而进行序列化,会抛出异常。 序列化的类需要实现 Serializable 接口,它只是一个标准,没有任何方法需要实现,但是如果不去实现它的话而进行序列化,会抛出异常。
```java ```java
public static void main(String[] args) throws IOException, ClassNotFoundException { public static void main(String[] args) throws IOException, ClassNotFoundException
{
A a1 = new A(123, "abc"); A a1 = new A(123, "abc");
String objectFile = "file/a1"; String objectFile = "file/a1";
ObjectOutputStream objectOutputStream = new ObjectOutputStream(new FileOutputStream(objectFile)); ObjectOutputStream objectOutputStream = new ObjectOutputStream(new FileOutputStream(objectFile));
objectOutputStream.writeObject(a1); objectOutputStream.writeObject(a1);
objectOutputStream.close(); objectOutputStream.close();
ObjectInputStream objectInputStream = new ObjectInputStream(new FileInputStream(objectFile)); ObjectInputStream objectInputStream = new ObjectInputStream(new FileInputStream(objectFile));
A a2 = (A) objectInputStream.readObject(); A a2 = (A) objectInputStream.readObject();
objectInputStream.close(); objectInputStream.close();
System.out.println(a2); System.out.println(a2);
} }
private static class A implements Serializable { private static class A implements Serializable
{
private int x; private int x;
private String y; private String y;
A(int x, String y) { A(int x, String y)
{
this.x = x; this.x = x;
this.y = y; this.y = y;
} }
@Override @Override
public String toString() { public String toString()
return "x = " + x + {
" " + "y = " + y; return "x = " + x + " " + "y = " + y;
} }
} }
``` ```
@ -202,16 +213,19 @@ InetAddress.getByAddress(byte[] address);
可以直接从 URL 中读取字节流数据。 可以直接从 URL 中读取字节流数据。
```java ```java
URL url = new URL("http://www.baidu.com"); public static void main(String[] args) throws IOException
InputStream is = url.openStream(); // 字节流 {
InputStreamReader isr = new InputStreamReader(is, "utf-8"); // 字符流 URL url = new URL("http://www.baidu.com");
BufferedReader br = new BufferedReader(isr); InputStream is = url.openStream(); /* 字节流 */
String line = br.readLine(); InputStreamReader isr = new InputStreamReader(is, "utf-8"); /* 字符流 */
while (line != null) { BufferedReader br = new BufferedReader(isr);
String line = br.readLine();
while (line != null) {
System.out.println(line); System.out.println(line);
line = br.readLine(); line = br.readLine();
}
br.close();
} }
br.close();
``` ```
## Sockets ## Sockets

View File

@ -2526,7 +2526,8 @@ public ArrayList<ArrayList<Integer>> FindContinuousSequence(int sum) {
正确的解法应该是和书上一样,先旋转每个单词,再旋转整个字符串。 正确的解法应该是和书上一样,先旋转每个单词,再旋转整个字符串。
```java ```java
public String ReverseSentence(String str) { public String ReverseSentence(String str)
{
int n = str.length(); int n = str.length();
char[] chars = str.toCharArray(); char[] chars = str.toCharArray();
int i = 0, j = 0; int i = 0, j = 0;
@ -2541,12 +2542,14 @@ public String ReverseSentence(String str) {
return new String(chars); return new String(chars);
} }
private void reverse(char[] c, int i, int j) { private void reverse(char[] c, int i, int j)
{
while (i < j) while (i < j)
swap(c, i++, j--); swap(c, i++, j--);
} }
private void swap(char[] c, int i, int j) { private void swap(char[] c, int i, int j)
{
char t = c[i]; char t = c[i];
c[i] = c[j]; c[i] = c[j];
c[j] = t; c[j] = t;
@ -2566,7 +2569,8 @@ private void swap(char[] c, int i, int j) {
将 "abcXYZdef" 旋转左移三位,可以先将 "abc" 和 "XYZdef" 分别旋转,得到 "cbafedZYX",然后再把整个字符串旋转得到 "XYZdefabc"。 将 "abcXYZdef" 旋转左移三位,可以先将 "abc" 和 "XYZdef" 分别旋转,得到 "cbafedZYX",然后再把整个字符串旋转得到 "XYZdefabc"。
```java ```java
public String LeftRotateString(String str, int n) { public String LeftRotateString(String str, int n)
{
if (n >= str.length()) if (n >= str.length())
return str; return str;
char[] chars = str.toCharArray(); char[] chars = str.toCharArray();
@ -2576,12 +2580,14 @@ public String LeftRotateString(String str, int n) {
return new String(chars); return new String(chars);
} }
private void reverse(char[] chars, int i, int j) { private void reverse(char[] chars, int i, int j)
{
while (i < j) while (i < j)
swap(chars, i++, j--); swap(chars, i++, j--);
} }
private void swap(char[] chars, int i, int j) { private void swap(char[] chars, int i, int j)
{
char t = chars[i]; char t = chars[i];
chars[i] = chars[j]; chars[i] = chars[j];
chars[j] = t; chars[j] = t;
@ -2599,15 +2605,16 @@ private void swap(char[] chars, int i, int j) {
## 解题思路 ## 解题思路
```java ```java
public ArrayList<Integer> maxInWindows(int[] num, int size) { public ArrayList<Integer> maxInWindows(int[] num, int size)
{
ArrayList<Integer> ret = new ArrayList<>(); ArrayList<Integer> ret = new ArrayList<>();
PriorityQueue<Integer> heap = new PriorityQueue<Integer>((o1, o2) -> o2 - o1);
if (size > num.length || size < 1) if (size > num.length || size < 1)
return ret; return ret;
PriorityQueue<Integer> heap = new PriorityQueue<>((o1, o2) -> o2 - o1); /* 大顶堆 */
for (int i = 0; i < size; i++) for (int i = 0; i < size; i++)
heap.add(num[i]); heap.add(num[i]);
ret.add(heap.peek()); ret.add(heap.peek());
for (int i = 1, j = i + size - 1; j < num.length; i++, j++) { for (int i = 1, j = i + size - 1; j < num.length; i++, j++) { /* 维护一个大小为 size 的大顶堆 */
heap.remove(num[i - 1]); heap.remove(num[i - 1]);
heap.add(num[j]); heap.add(num[j]);
ret.add(heap.peek()); ret.add(heap.peek());
@ -2633,15 +2640,17 @@ public ArrayList<Integer> maxInWindows(int[] num, int size) {
空间复杂度O(N<sup>2</sup>) 空间复杂度O(N<sup>2</sup>)
```java ```java
public List<Map.Entry<Integer, Double>> dicesSum(int n) { public List<Map.Entry<Integer, Double>> dicesSum(int n)
{
final int face = 6; final int face = 6;
final int pointNum = face * n; final int pointNum = face * n;
long[][] dp = new long[n + 1][pointNum + 1]; long[][] dp = new long[n + 1][pointNum + 1];
for (int i = 1; i <= face; i++) for (int i = 1; i <= face; i++)
dp[1][i] = 1; dp[1][i] = 1;
for (int i = 2; i <= n; i++) for (int i = 2; i <= n; i++)
for (int j = i; j <= pointNum; j++) // 使用 i 个骰子最小点数为 i for (int j = i; j <= pointNum; j++) /* 使用 i 个骰子最小点数为 i */
for (int k = 1; k <= face && k <= j; k++) for (int k = 1; k <= face && k <= j; k++)
dp[i][j] += dp[i - 1][j - k]; dp[i][j] += dp[i - 1][j - k];
@ -2649,6 +2658,7 @@ public List<Map.Entry<Integer, Double>> dicesSum(int n) {
List<Map.Entry<Integer, Double>> ret = new ArrayList<>(); List<Map.Entry<Integer, Double>> ret = new ArrayList<>();
for (int i = n; i <= pointNum; i++) for (int i = n; i <= pointNum; i++)
ret.add(new AbstractMap.SimpleEntry<>(i, dp[n][i] / totalNum)); ret.add(new AbstractMap.SimpleEntry<>(i, dp[n][i] / totalNum));
return ret; return ret;
} }
``` ```
@ -2658,24 +2668,30 @@ public List<Map.Entry<Integer, Double>> dicesSum(int n) {
空间复杂度O(N) 空间复杂度O(N)
```java ```java
public List<Map.Entry<Integer, Double>> dicesSum(int n) { public List<Map.Entry<Integer, Double>> dicesSum(int n)
{
final int face = 6; final int face = 6;
final int pointNum = face * n; final int pointNum = face * n;
long[][] dp = new long[2][pointNum + 1]; long[][] dp = new long[2][pointNum + 1];
for (int i = 1; i <= face; i++) for (int i = 1; i <= face; i++)
dp[0][i] = 1; dp[0][i] = 1;
int flag = 1;
int flag = 1; /* 旋转标记 */
for (int i = 2; i <= n; i++, flag = 1 - flag) { for (int i = 2; i <= n; i++, flag = 1 - flag) {
for (int j = 0; j <= pointNum; j++) for (int j = 0; j <= pointNum; j++)
dp[flag][j] = 0; // 旋转数组清零 dp[flag][j] = 0; /* 旋转数组清零 */
for (int j = i; j <= pointNum; j++) // 使用 i 个骰子最小点数为 i
for (int j = i; j <= pointNum; j++)
for (int k = 1; k <= face && k <= j; k++) for (int k = 1; k <= face && k <= j; k++)
dp[flag][j] += dp[1 - flag][j - k]; dp[flag][j] += dp[1 - flag][j - k];
} }
final double totalNum = Math.pow(6, n); final double totalNum = Math.pow(6, n);
List<Map.Entry<Integer, Double>> ret = new ArrayList<>(); List<Map.Entry<Integer, Double>> ret = new ArrayList<>();
for (int i = n; i <= pointNum; i++) for (int i = n; i <= pointNum; i++)
ret.add(new AbstractMap.SimpleEntry<>(i, dp[1 - flag][i] / totalNum)); ret.add(new AbstractMap.SimpleEntry<>(i, dp[1 - flag][i] / totalNum));
return ret; return ret;
} }
``` ```
@ -2691,18 +2707,20 @@ public List<Map.Entry<Integer, Double>> dicesSum(int n) {
## 解题思路 ## 解题思路
```java ```java
public boolean isContinuous(int[] nums) { public boolean isContinuous(int[] nums)
{
if (nums.length < 5) if (nums.length < 5)
return false; return false;
Arrays.sort(nums); Arrays.sort(nums);
int cnt = 0; int cnt = 0;
for (int num : nums) for (int num : nums) /* 统计癞子数量 */
if (num == 0) if (num == 0)
cnt++; cnt++;
for (int i = cnt; i < nums.length - 1; i++) { for (int i = cnt; i < nums.length - 1; i++) {
if (nums[i + 1] == nums[i]) if (nums[i + 1] == nums[i])
return false; return false;
cnt -= nums[i + 1] - nums[i] - 1; cnt -= nums[i + 1] - nums[i] - 1; /* 使用癞子去补全不连续的顺子 */
} }
return cnt >= 0; return cnt >= 0;
} }
@ -2721,10 +2739,11 @@ public boolean isContinuous(int[] nums) {
约瑟夫环,圆圈长度为 n 的解可以看成长度为 n-1 的解再加上报数的长度 m。因为是圆圈所以最后需要对 n 取余。 约瑟夫环,圆圈长度为 n 的解可以看成长度为 n-1 的解再加上报数的长度 m。因为是圆圈所以最后需要对 n 取余。
```java ```java
public int LastRemaining_Solution(int n, int m) { public int LastRemaining_Solution(int n, int m)
if (n == 0) {
if (n == 0) /* 特殊输入的处理 */
return -1; return -1;
if (n == 1) if (n == 1) /* 返回条件 */
return 0; return 0;
return (LastRemaining_Solution(n - 1, m) + m) % n; return (LastRemaining_Solution(n - 1, m) + m) % n;
} }
@ -2743,13 +2762,13 @@ public int LastRemaining_Solution(int n, int m) {
使用贪心策略,假设第 i 轮进行卖出操作,买入操作价格应该在 i 之前并且价格最低。 使用贪心策略,假设第 i 轮进行卖出操作,买入操作价格应该在 i 之前并且价格最低。
```java ```java
public int maxProfit(int[] prices) { public int maxProfit(int[] prices)
{
if (prices == null || prices.length == 0) if (prices == null || prices.length == 0)
return 0; return 0;
int n = prices.length;
int soFarMin = prices[0]; int soFarMin = prices[0];
int maxProfit = 0; int maxProfit = 0;
for (int i = 1; i < n; i++) { for (int i = 1; i < prices.length; i++) {
soFarMin = Math.min(soFarMin, prices[i]); soFarMin = Math.min(soFarMin, prices[i]);
maxProfit = Math.max(maxProfit, prices[i] - soFarMin); maxProfit = Math.max(maxProfit, prices[i] - soFarMin);
} }
@ -2774,7 +2793,8 @@ public int maxProfit(int[] prices) {
以下实现中,递归的返回条件为 n <= 0取非后就是 n > 0递归的主体部分为 sum += Sum_Solution(n - 1),转换为条件语句后就是 (sum += Sum_Solution(n - 1)) > 0。 以下实现中,递归的返回条件为 n <= 0取非后就是 n > 0递归的主体部分为 sum += Sum_Solution(n - 1),转换为条件语句后就是 (sum += Sum_Solution(n - 1)) > 0。
```java ```java
public int Sum_Solution(int n) { public int Sum_Solution(int n)
{
int sum = n; int sum = n;
boolean b = (n > 0) && ((sum += Sum_Solution(n - 1)) > 0); boolean b = (n > 0) && ((sum += Sum_Solution(n - 1)) > 0);
return sum; return sum;
@ -2796,8 +2816,9 @@ a ^ b 表示没有考虑进位的情况下两数的和,(a & b) << 1 就是进
递归会终止的原因是 (a & b) << 1 最右边会多一个 0那么继续递归进位最右边的 0 会慢慢增多最后进位会变为 0递归终止 递归会终止的原因是 (a & b) << 1 最右边会多一个 0那么继续递归进位最右边的 0 会慢慢增多最后进位会变为 0递归终止
```java ```java
public int Add(int num1, int num2) { public int Add(int a, int b)
return num2 == 0 ? num1 : Add(num1 ^ num2, (num1 & num2) << 1); {
return b == 0 ? a : Add(a ^ b, (a & b) << 1);
} }
``` ```
@ -2812,12 +2833,13 @@ public int Add(int num1, int num2) {
## 解题思路 ## 解题思路
```java ```java
public int[] multiply(int[] A) { public int[] multiply(int[] A)
{
int n = A.length; int n = A.length;
int[] B = new int[n]; int[] B = new int[n];
for (int i = 0, product = 1; i < n; product *= A[i], i++) for (int i = 0, product = 1; i < n; product *= A[i], i++) /* 从左往右累乘 */
B[i] = product; B[i] = product;
for (int i = n - 1, product = 1; i >= 0; product *= A[i], i--) for (int i = n - 1, product = 1; i >= 0; product *= A[i], i--) /* 从右往左累乘 */
B[i] *= product; B[i] *= product;
return B; return B;
} }
@ -2844,17 +2866,18 @@ Output:
## 解题思路 ## 解题思路
```java ```java
public int StrToInt(String str) { public int StrToInt(String str)
{
if (str == null || str.length() == 0) if (str == null || str.length() == 0)
return 0; return 0;
boolean isNegative = str.charAt(0) == '-'; boolean isNegative = str.charAt(0) == '-';
int ret = 0; int ret = 0;
for (int i = 0; i < str.length(); i++) { for (int i = 0; i < str.length(); i++) {
char c = str.charAt(i); char c = str.charAt(i);
if (i == 0 && (c == '+' || c == '-')) if (i == 0 && (c == '+' || c == '-')) /* 符号判定 */
continue; continue;
if (c < '0' || c > '9') if (c < '0' || c > '9') /* 非法输入 */
return 0; // 非法输入 return 0;
ret = ret * 10 + (c - '0'); ret = ret * 10 + (c - '0');
} }
return isNegative ? -ret : ret; return isNegative ? -ret : ret;
@ -2891,7 +2914,7 @@ public TreeNode lowestCommonAncestor(TreeNode root, TreeNode p, TreeNode q) {
[Leetcode : 236. Lowest Common Ancestor of a Binary Tree](https://leetcode.com/problems/lowest-common-ancestor-of-a-binary-tree/description/) [Leetcode : 236. Lowest Common Ancestor of a Binary Tree](https://leetcode.com/problems/lowest-common-ancestor-of-a-binary-tree/description/)
在左右子树中查找两个节点的最低公共祖先,如果在其中一颗子树中查找到,那么就返回这个解,否则可以认为根节点就是最低公共祖先 在左右子树中查找是否存在 p 或者 q如果 p 和 q 分别在两个子树中,那么就说明根节点就是 LCA
```java ```java
public TreeNode lowestCommonAncestor(TreeNode root, TreeNode p, TreeNode q) { public TreeNode lowestCommonAncestor(TreeNode root, TreeNode p, TreeNode q) {