提交 6c274c42 编写于 作者: C CyC2018

auto commit

上级 ae1e1404
......@@ -263,7 +263,7 @@ Output: 1
```java
public int findMin(int[] nums) {
int l = 0, h = nums.length;
int l = 0, h = nums.length - 1;
while (l < h) {
int m = l + (h - l) / 2;
if (nums[m] <= nums[h]) h = m;
......
......@@ -909,15 +909,15 @@ public ListNode deleteNode(ListNode head, ListNode tobeDelete) {
```java
public ListNode deleteDuplication(ListNode pHead) {
if (pHead == null) return null;
if (pHead == null || pHead.next == null) return pHead;
ListNode next = pHead.next;
if (next == null) return pHead;
if (pHead.val == next.val) {
while (next != null && pHead.val == next.val) next = next.next;
return deleteDuplication(next);
} else {
pHead.next = deleteDuplication(pHead.next);
return pHead;
}
pHead.next = deleteDuplication(pHead.next);
return pHead;
}
```
......@@ -2256,6 +2256,8 @@ private int height(TreeNode root) {
## 题目描述
[NowCoder](https://www.nowcoder.com/practice/e02fdb54d7524710a7d664d082bb7811?tpId=13&tqId=11193&tPage=1&rp=1&ru=/ta/coding-interviews&qru=/ta/coding-interviews/question-ranking)
一个整型数组里除了两个数字之外,其他的数字都出现了两次,找出这两个数。
## 解题思路
......@@ -2267,40 +2269,49 @@ private int height(TreeNode root) {
diff &= -diff 得到出 diff 最右侧不为 0 的位,也就是不存在重复的两个元素在位级表示上最右侧不同的那一位,利用这一位就可以将两个元素区分开来。
```java
public void FindNumsAppearOnce(int[] array, int num1[], int num2[]) {
int diff = 0;
for (int num : array) diff ^= num;
// 得到最右一位
diff &= -diff;
for (int num : array) {
if ((num & diff) == 0) num1[0] ^= num;
else num2[0] ^= num;
public void FindNumsAppearOnce(int[] nums, int num1[], int num2[]) {
int diff = 0;
for (int num : nums) {
diff ^= num;
}
// 得到最右一位
diff &= -diff;
for (int num : nums) {
if ((num & diff) == 0) {
num1[0] ^= num;
} else {
num2[0] ^= num;
}
}
}
}
```
# 57.1 和为 S 的两个数字
## 题目描述
[NowCoder](https://www.nowcoder.com/practice/390da4f7a00f44bea7c2f3d19491311b?tpId=13&tqId=11195&tPage=1&rp=1&ru=/ta/coding-interviews&qru=/ta/coding-interviews/question-ranking)
输入一个递增排序的数组和一个数字 S,在数组中查找两个数,使得他们的和正好是 S,如果有多对数字的和等于 S,输出两个数的乘积最小的。
## 解题思路
使用双指针,一个指针指向元素较小的值,一个指针指向元素较大的值。指向较小元素的指针从头向尾遍历,指向较大元素的指针从尾向头遍历。
如果两个指针指向元素的和 sum == target,那么得到要求的结果;如果 sum > target,移动较大的元素,使 sum 变小一些;如果 sum < target,移动较小的元素,使 sum 变大一些。
- 如果两个指针指向元素的和 sum == target,那么得到要求的结果;
- 如果 sum > target,移动较大的元素,使 sum 变小一些;
- 如果 sum < target,移动较小的元素,使 sum 变大一些。
```java
public ArrayList<Integer> FindNumbersWithSum(int[] array, int sum) {
int i = 0, j = array.length - 1;
while (i < j) {
int cur = array[i] + array[j];
if (cur == sum) return new ArrayList<Integer>(Arrays.asList(array[i], array[j]));
else if (cur < sum) i++;
if (cur == sum) return new ArrayList<>(Arrays.asList(array[i], array[j]));
if (cur < sum) i++;
else j--;
}
return new ArrayList<Integer>();
return new ArrayList<>();
}
```
......@@ -2308,32 +2319,41 @@ public ArrayList<Integer> FindNumbersWithSum(int[] array, int sum) {
## 题目描述
和为 100 的连续序列有 18, 19, 20, 21, 22。
[NowCoder](https://www.nowcoder.com/practice/c451a3fd84b64cb19485dad758a55ebe?tpId=13&tqId=11194&tPage=1&rp=1&ru=/ta/coding-interviews&qru=/ta/coding-interviews/question-ranking)
输出所有和为 S 的连续正数序列。序列内按照从小至大的顺序,序列间按照开始数字从小到大的顺序
例如和为 100 的连续序列有:
```
[9, 10, 11, 12, 13, 14, 15, 16]
[18, 19, 20, 21, 22]。
```
## 解题思路
```java
public ArrayList<ArrayList<Integer>> FindContinuousSequence(int sum) {
ArrayList<ArrayList<Integer>> ret = new ArrayList<>();
int first = 1, last = 2;
int start = 1, end = 2;
int curSum = 3;
while (first <= sum / 2 && last < sum) {
while (end < sum) {
if (curSum > sum) {
curSum -= first;
first++;
curSum -= start;
start++;
} else if (curSum < sum) {
last++;
curSum += last;
end++;
curSum += end;
} else {
ArrayList<Integer> list = new ArrayList<>();
for (int i = first; i <= last; i++) {
for (int i = start; i <= end; i++) {
list.add(i);
}
ret.add(list);
curSum -= first;
first++;
last++;
curSum += last;
curSum -= start;
start++;
end++;
curSum += end;
}
}
return ret;
......@@ -2350,11 +2370,14 @@ public ArrayList<ArrayList<Integer>> FindContinuousSequence(int sum) {
## 解题思路
题目应该有一个隐含条件,就是不能用额外的空间。虽然 Java 的题目输入参数为 String 类型,需要先创建一个字符数组使得空间复杂度为 O(n),但是正确的参数类型应该和原书一样,为字符数组,并且只能使用该字符数组的空间。任何使用了额外空间的解法在面试时都会大打折扣,包括递归解法。正确的解法应该是和书上一样,先旋转每个单词,再旋转整个字符串。
[NowCoder](https://www.nowcoder.com/practice/3194a4f4cf814f63919d0790578d51f3?tpId=13&tqId=11197&tPage=1&rp=1&ru=/ta/coding-interviews&qru=/ta/coding-interviews/question-ranking)
题目应该有一个隐含条件,就是不能用额外的空间。虽然 Java 的题目输入参数为 String 类型,需要先创建一个字符数组使得空间复杂度为 O(N),但是正确的参数类型应该和原书一样,为字符数组,并且只能使用该字符数组的空间。任何使用了额外空间的解法在面试时都会大打折扣,包括递归解法。
正确的解法应该是和书上一样,先旋转每个单词,再旋转整个字符串。
```java
public String ReverseSentence(String str) {
if (str.length() == 0) return str;
int n = str.length();
char[] chars = str.toCharArray();
int i = 0, j = 0;
......@@ -2370,43 +2393,59 @@ public String ReverseSentence(String str) {
}
private void reverse(char[] c, int i, int j) {
while(i < j) {
char t = c[i]; c[i] = c[j]; c[j] = t;
i++; j--;
while (i < j) {
swap(c, i++, j--);
}
}
private void swap(char[] c, int i, int j) {
char t = c[i];
c[i] = c[j];
c[j] = t;
}
```
# 58.2 左旋转字符串
## 题目描述
[NowCoder](https://www.nowcoder.com/practice/12d959b108cb42b1ab72cef4d36af5ec?tpId=13&tqId=11196&tPage=1&rp=1&ru=/ta/coding-interviews&qru=/ta/coding-interviews/question-ranking)
对于一个给定的字符序列 S,请你把其循环左移 K 位后的序列输出。例如,字符序列 S=”abcXYZdef”, 要求输出循环左移 3 位后的结果,即“XYZdefabc”。
## 解题思路
将 "abcXYZdef" 旋转左移三位,可以先将 "abc" 和 "XYZdef" 分别旋转,得到 "cbafedZYX",然后再把整个字符串旋转得到 "XYZdefabc"。
```java
public String LeftRotateString(String str, int n) {
if(str.length() == 0) return "";
char[] c = str.toCharArray();
reverse(c, 0, n - 1);
reverse(c, n, c.length - 1);
reverse(c, 0, c.length - 1);
return new String(c);
if (n >= str.length()) return str;
char[] chars = str.toCharArray();
reverse(chars, 0, n - 1);
reverse(chars, n, chars.length - 1);
reverse(chars, 0, chars.length - 1);
return new String(chars);
}
private void reverse(char[] c, int i, int j) {
while(i < j) {
char t = c[i]; c[i] = c[j]; c[j] = t;
i++; j--;
private void reverse(char[] chars, int i, int j) {
while (i < j) {
swap(chars, i++, j--);
}
}
private void swap(char[] chars, int i, int j) {
char t = chars[i];
chars[i] = chars[j];
chars[j] = t;
}
```
# 59. 滑动窗口的最大值
## 题目描述
[NowCoder](https://www.nowcoder.com/practice/1624bc35a45c42c0bc17d17fa0cba788?tpId=13&tqId=11217&tPage=1&rp=1&ru=/ta/coding-interviews&qru=/ta/coding-interviews/question-ranking)
给定一个数组和滑动窗口的大小,找出所有滑动窗口里数值的最大值。例如,如果输入数组 {2, 3, 4, 2, 6, 2, 5, 1} 及滑动窗口的大小 3,那么一共存在 6 个滑动窗口,他们的最大值分别为 {4, 4, 6, 6, 6, 5}。
## 解题思路
......@@ -2414,14 +2453,13 @@ private void reverse(char[] c, int i, int j) {
```java
public ArrayList<Integer> maxInWindows(int[] num, int size) {
ArrayList<Integer> ret = new ArrayList<>();
if (size > num.length || size < 1) return ret;
// 构建最大堆,即堆顶元素是堆的最大值。
PriorityQueue<Integer> heap = new PriorityQueue<Integer>((o1, o2) -> o2 - o1);
if (size > num.length || size < 1) return ret;
for (int i = 0; i < size; i++) heap.add(num[i]);
ret.add(heap.peek());
for (int i = 1; i + size - 1 < num.length; i++) {
for (int i = 1, j = i + size - 1; j < num.length; i++, j++) {
heap.remove(num[i - 1]);
heap.add(num[i + size - 1]);
heap.add(num[j]);
ret.add(heap.peek());
}
return ret;
......@@ -2432,35 +2470,39 @@ public ArrayList<Integer> maxInWindows(int[] num, int size) {
## 题目描述
[Lintcode](https://www.lintcode.com/en/problem/dices-sum/)
把 n 个骰子仍在地上,求点数和为 s 的概率。
## 解题思路
### 动态规划解法
使用一个二维数组 dp 存储点数出现的次数,其中 dp[i][j] 表示前 i 个骰子产生点数 j 的次数。
空间复杂度:O(N<sup>2</sup>)
```java
private static int face = 6;
public double countProbability(int n, int s) {
if (n < 1 || s < n) return 0.0;
int pointNum = face * n;
int[][] dp = new int[n][pointNum];
for (int i = 0; i < face; i++) {
dp[0][i] = 1;
public List<Map.Entry<Integer, Double>> dicesSum(int n) {
final int face = 6;
final int pointNum = face * n;
long[][] dp = new long[n + 1][pointNum + 1];
for (int i = 1; i <= face; i++) {
dp[1][i] = 1;
}
for (int i = 1; i < n; i++) {
for (int j = i; j < pointNum; j++) { // 使用 i 个骰子最小点数为 i
for (int k = 1; k <= face; k++) {
if (j - k >= 0) {
dp[i][j] += dp[i - 1][j - k];
}
for (int i = 2; i <= n; i++) {
for (int j = i; j <= pointNum; j++) { // 使用 i 个骰子最小点数为 i
for (int k = 1; k <= face && k <= j; k++) {
dp[i][j] += dp[i - 1][j - k];
}
}
}
int totalNum = (int) Math.pow(6, n);
return (double) dp[n - 1][s - 1] / totalNum;
final double totalNum = Math.pow(6, n);
List<Map.Entry<Integer, Double>> ret = new ArrayList<>();
for (int i = n; i <= pointNum; i++) {
ret.add(new AbstractMap.SimpleEntry<>(i, dp[n][i] / totalNum));
}
return ret;
}
```
......@@ -2469,28 +2511,30 @@ public double countProbability(int n, int s) {
空间复杂度:O(N)
```java
private static int face = 6;
public double countProbability(int n, int s) {
if (n < 1 || s < n) return 0.0;
int pointNum = face * n;
int[][] dp = new int[2][pointNum];
for (int i = 0; i < face; i++) {
public List<Map.Entry<Integer, Double>> dicesSum(int n) {
final int face = 6;
final int pointNum = face * n;
long[][] dp = new long[2][pointNum + 1];
for (int i = 1; i <= face; i++) {
dp[0][i] = 1;
}
int flag = 1;
for (int i = 1; i < n; i++) {
for (int j = i; j < pointNum; j++) { // 使用 i 个骰子最小点数为 i
for (int k = 1; k <= face; k++) {
if (j - k >= 0) {
dp[flag][j] += dp[1 - flag][j - k];
}
for (int i = 2; i <= n; i++, flag = 1 - flag) {
for (int j = 0; j <= pointNum; j++) {
dp[flag][j] = 0; // 旋转数组清零
}
for (int j = i; j <= pointNum; j++) { // 使用 i 个骰子最小点数为 i
for (int k = 1; k <= face && k <= j; k++) {
dp[flag][j] += dp[1 - flag][j - k];
}
}
flag = 1 - flag;
}
int totalNum = (int) Math.pow(6, n);
return (double) dp[flag][s - 1] / totalNum;
final double totalNum = Math.pow(6, n);
List<Map.Entry<Integer, Double>> ret = new ArrayList<>();
for (int i = n; i <= pointNum; i++) {
ret.add(new AbstractMap.SimpleEntry<>(i, dp[1 - flag][i] / totalNum));
}
return ret;
}
```
......
......@@ -328,7 +328,7 @@ aBCd
# 九、前后查找
前后查找规定了匹配的内容首尾应该匹配的内容,但是又不包含首尾匹配的内容。向前查找用 **?=** 来定义,它规定了尾部匹配的内容,这个匹配的内容在 ?= 之后定义。所谓向前查找,就是规定了一个匹配的内容,然后以这个内容为尾部向前面查找需要匹配的内容。向后匹配用 ?<= 定义(注:javaScript不支持向后匹配,java对其支持也不完善)。
前后查找规定了匹配的内容首尾应该匹配的内容,但是又不包含首尾匹配的内容。向前查找用 **?=** 来定义,它规定了尾部匹配的内容,这个匹配的内容在 ?= 之后定义。所谓向前查找,就是规定了一个匹配的内容,然后以这个内容为尾部向前面查找需要匹配的内容。向后匹配用 ?<= 定义(注: javaScript 不支持向后匹配, java 对其支持也不完善)。
**应用**
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册