提交 9807ff68 编写于 作者: C CyC2018

auto commit

上级 ea236194
...@@ -1706,16 +1706,18 @@ public class Solution { ...@@ -1706,16 +1706,18 @@ public class Solution {
```java ```java
private ArrayList<String> ret = new ArrayList<>(); private ArrayList<String> ret = new ArrayList<>();
public ArrayList<String> Permutation(String str) { public ArrayList<String> Permutation(String str)
{
if (str.length() == 0) if (str.length() == 0)
return ret; return ret;
char[] chars = str.toCharArray(); char[] chars = str.toCharArray();
Arrays.sort(chars); Arrays.sort(chars);
backtracking(chars, new boolean[chars.length], new StringBuffer()); backtracking(chars, new boolean[chars.length], new StringBuilder());
return ret; return ret;
} }
private void backtracking(char[] chars, boolean[] hasUsed, StringBuffer s) { private void backtracking(char[] chars, boolean[] hasUsed, StringBuilder s)
{
if (s.length() == chars.length) { if (s.length() == chars.length) {
ret.add(s.toString()); ret.add(s.toString());
return; return;
...@@ -1723,7 +1725,7 @@ private void backtracking(char[] chars, boolean[] hasUsed, StringBuffer s) { ...@@ -1723,7 +1725,7 @@ private void backtracking(char[] chars, boolean[] hasUsed, StringBuffer s) {
for (int i = 0; i < chars.length; i++) { for (int i = 0; i < chars.length; i++) {
if (hasUsed[i]) if (hasUsed[i])
continue; continue;
if (i != 0 && chars[i] == chars[i - 1] && !hasUsed[i - 1]) // 保证不重复 if (i != 0 && chars[i] == chars[i - 1] && !hasUsed[i - 1]) /* 保证不重复 */
continue; continue;
hasUsed[i] = true; hasUsed[i] = true;
s.append(chars[i]); s.append(chars[i]);
...@@ -1745,7 +1747,8 @@ private void backtracking(char[] chars, boolean[] hasUsed, StringBuffer s) { ...@@ -1745,7 +1747,8 @@ private void backtracking(char[] chars, boolean[] hasUsed, StringBuffer s) {
使用 cnt 来统计一个元素出现的次数,当遍历到的元素和统计元素不相等时,令 cnt--。如果前面查找了 i 个元素,且 cnt == 0 ,说明前 i 个元素没有 majority,或者有 majority,但是出现的次数少于 i / 2 ,因为如果多于 i / 2 的话 cnt 就一定不会为 0 。此时剩下的 n - i 个元素中,majority 的数目依然多于 (n - i) / 2,因此继续查找就能找出 majority。 使用 cnt 来统计一个元素出现的次数,当遍历到的元素和统计元素不相等时,令 cnt--。如果前面查找了 i 个元素,且 cnt == 0 ,说明前 i 个元素没有 majority,或者有 majority,但是出现的次数少于 i / 2 ,因为如果多于 i / 2 的话 cnt 就一定不会为 0 。此时剩下的 n - i 个元素中,majority 的数目依然多于 (n - i) / 2,因此继续查找就能找出 majority。
```java ```java
public int MoreThanHalfNum_Solution(int[] nums) { public int MoreThanHalfNum_Solution(int[] nums)
{
int majority = nums[0]; int majority = nums[0];
for (int i = 1, cnt = 1; i < nums.length; i++) { for (int i = 1, cnt = 1; i < nums.length; i++) {
cnt = nums[i] == majority ? cnt + 1 : cnt - 1; cnt = nums[i] == majority ? cnt + 1 : cnt - 1;
...@@ -1776,18 +1779,20 @@ public int MoreThanHalfNum_Solution(int[] nums) { ...@@ -1776,18 +1779,20 @@ public int MoreThanHalfNum_Solution(int[] nums) {
快速排序的 partition() 方法,会返回一个整数 j 使得 a[l..j-1] 小于等于 a[j],且 a[j+1..h] 大于等于 a[j],此时 a[j] 就是数组的第 j 大元素。可以利用这个特性找出数组的第 K 个元素,这种找第 K 个元素的算法称为快速选择算法。 快速排序的 partition() 方法,会返回一个整数 j 使得 a[l..j-1] 小于等于 a[j],且 a[j+1..h] 大于等于 a[j],此时 a[j] 就是数组的第 j 大元素。可以利用这个特性找出数组的第 K 个元素,这种找第 K 个元素的算法称为快速选择算法。
```java ```java
public ArrayList<Integer> GetLeastNumbers_Solution(int[] nums, int k) { public ArrayList<Integer> GetLeastNumbers_Solution(int[] nums, int k)
{
ArrayList<Integer> ret = new ArrayList<>(); ArrayList<Integer> ret = new ArrayList<>();
if (k > nums.length || k <= 0) if (k > nums.length || k <= 0)
return ret; return ret;
int kthSmallest = findKthSmallest(nums, k - 1); findKthSmallest(nums, k - 1);
// findKthSmallest 会改变数组,使得前 k 个数都是最小的 k 个数 /* findKthSmallest 会改变数组,使得前 k 个数都是最小的 k 个数 */
for (int i = 0; i < k; i++) for (int i = 0; i < k; i++)
ret.add(nums[i]); ret.add(nums[i]);
return ret; return ret;
} }
public int findKthSmallest(int[] nums, int k) { public void findKthSmallest(int[] nums, int k)
{
int l = 0, h = nums.length - 1; int l = 0, h = nums.length - 1;
while (l < h) { while (l < h) {
int j = partition(nums, l, h); int j = partition(nums, l, h);
...@@ -1798,16 +1803,15 @@ public int findKthSmallest(int[] nums, int k) { ...@@ -1798,16 +1803,15 @@ public int findKthSmallest(int[] nums, int k) {
else else
l = j + 1; l = j + 1;
} }
return nums[k];
} }
private int partition(int[] nums, int l, int h) { private int partition(int[] nums, int l, int h)
// 切分元素 {
int parti = nums[l]; int p = nums[l]; /* 切分元素 */
int i = l, j = h + 1; int i = l, j = h + 1;
while (true) { while (true) {
while (i != h && nums[++i] < parti) ; while (i != h && nums[++i] < p) ;
while (j != l && nums[--j] > parti) ; while (j != l && nums[--j] > p) ;
if (i >= j) if (i >= j)
break; break;
swap(nums, i, j); swap(nums, i, j);
...@@ -1816,7 +1820,8 @@ private int partition(int[] nums, int l, int h) { ...@@ -1816,7 +1820,8 @@ private int partition(int[] nums, int l, int h) {
return j; return j;
} }
private void swap(int[] nums, int i, int j) { private void swap(int[] nums, int i, int j)
{
int t = nums[i]; int t = nums[i];
nums[i] = nums[j]; nums[i] = nums[j];
nums[j] = t; nums[j] = t;
...@@ -1833,7 +1838,8 @@ private void swap(int[] nums, int i, int j) { ...@@ -1833,7 +1838,8 @@ private void swap(int[] nums, int i, int j) {
维护一个大小为 K 的最小堆过程如下:在添加一个元素之后,如果大顶堆的大小大于 K,那么需要将大顶堆的堆顶元素去除。 维护一个大小为 K 的最小堆过程如下:在添加一个元素之后,如果大顶堆的大小大于 K,那么需要将大顶堆的堆顶元素去除。
```java ```java
public ArrayList<Integer> GetLeastNumbers_Solution(int[] nums, int k) { public ArrayList<Integer> GetLeastNumbers_Solution(int[] nums, int k)
{
if (k > nums.length || k <= 0) if (k > nums.length || k <= 0)
return new ArrayList<>(); return new ArrayList<>();
PriorityQueue<Integer> maxHeap = new PriorityQueue<>((o1, o2) -> o2 - o1); PriorityQueue<Integer> maxHeap = new PriorityQueue<>((o1, o2) -> o2 - o1);
...@@ -1842,8 +1848,7 @@ public ArrayList<Integer> GetLeastNumbers_Solution(int[] nums, int k) { ...@@ -1842,8 +1848,7 @@ public ArrayList<Integer> GetLeastNumbers_Solution(int[] nums, int k) {
if (maxHeap.size() > k) if (maxHeap.size() > k)
maxHeap.poll(); maxHeap.poll();
} }
ArrayList<Integer> ret = new ArrayList<>(maxHeap); return new ArrayList<>(maxHeap) ;
return ret;
} }
``` ```
...@@ -1858,35 +1863,35 @@ public ArrayList<Integer> GetLeastNumbers_Solution(int[] nums, int k) { ...@@ -1858,35 +1863,35 @@ public ArrayList<Integer> GetLeastNumbers_Solution(int[] nums, int k) {
## 解题思路 ## 解题思路
```java ```java
public class Solution { /* 大顶堆,存储左半边元素 */
// 大顶堆,存储左半边元素 private PriorityQueue<Integer> left = new PriorityQueue<>((o1, o2) -> o2 - o1);
private PriorityQueue<Integer> left = new PriorityQueue<>((o1, o2) -> o2 - o1); /* 小顶堆,存储右半边元素,并且右半边元素都大于左半边 */
// 小顶堆,存储右半边元素,并且右半边元素都大于左半边 private PriorityQueue<Integer> right = new PriorityQueue<>();
private PriorityQueue<Integer> right = new PriorityQueue<>(); /* 当前数据流读入的元素个数 */
// 当前数据流读入的元素个数 private int N = 0;
private int N = 0;
public void Insert(Integer val) {
// 插入要保证两个堆存于平衡状态
if (N % 2 == 0) {
// N 为偶数的情况下插入到右半边。
// 因为右半边元素都要大于左半边,但是新插入的元素不一定比左半边元素来的大,
// 因此需要先将元素插入左半边,然后利用左半边为大顶堆的特点,取出堆顶元素即为最大元素,此时插入右半边
left.add(val);
right.add(left.poll());
} else {
right.add(val);
left.add(right.poll());
}
N++;
}
public Double GetMedian() { public void Insert(Integer val)
if (N % 2 == 0) {
return (left.peek() + right.peek()) / 2.0; /* 插入要保证两个堆存于平衡状态 */
else if (N % 2 == 0) {
return (double) right.peek(); /* N 为偶数的情况下插入到右半边。
* 因为右半边元素都要大于左半边,但是新插入的元素不一定比左半边元素来的大,
* 因此需要先将元素插入左半边,然后利用左半边为大顶堆的特点,取出堆顶元素即为最大元素,此时插入右半边 */
left.add(val);
right.add(left.poll());
} else {
right.add(val);
left.add(right.poll());
} }
N++;
}
public Double GetMedian()
{
if (N % 2 == 0)
return (left.peek() + right.peek()) / 2.0;
else
return (double) right.peek();
} }
``` ```
...@@ -1904,14 +1909,16 @@ public class Solution { ...@@ -1904,14 +1909,16 @@ public class Solution {
private int[] cnts = new int[256]; private int[] cnts = new int[256];
private Queue<Character> queue = new LinkedList<>(); private Queue<Character> queue = new LinkedList<>();
public void Insert(char ch) { public void Insert(char ch)
{
cnts[ch]++; cnts[ch]++;
queue.add(ch); queue.add(ch);
while (!queue.isEmpty() && cnts[queue.peek()] > 1) while (!queue.isEmpty() && cnts[queue.peek()] > 1)
queue.poll(); queue.poll();
} }
public char FirstAppearingOnce() { public char FirstAppearingOnce()
{
return queue.isEmpty() ? '#' : queue.peek(); return queue.isEmpty() ? '#' : queue.peek();
} }
``` ```
...@@ -1927,16 +1934,17 @@ public char FirstAppearingOnce() { ...@@ -1927,16 +1934,17 @@ public char FirstAppearingOnce() {
## 解题思路 ## 解题思路
```java ```java
public int FindGreatestSumOfSubArray(int[] nums) { public int FindGreatestSumOfSubArray(int[] nums)
{
if (nums == null || nums.length == 0) if (nums == null || nums.length == 0)
return 0; return 0;
int ret = Integer.MIN_VALUE; int greatestSum = Integer.MIN_VALUE;
int sum = 0; int sum = 0;
for (int val : nums) { for (int val : nums) {
sum = sum <= 0 ? val : sum + val; sum = sum <= 0 ? val : sum + val;
ret = Math.max(ret, sum); greatestSum = Math.max(greatestSum, sum);
} }
return ret; return greatestSum;
} }
``` ```
...@@ -1947,7 +1955,8 @@ public int FindGreatestSumOfSubArray(int[] nums) { ...@@ -1947,7 +1955,8 @@ public int FindGreatestSumOfSubArray(int[] nums) {
## 解题思路 ## 解题思路
```java ```java
public int NumberOf1Between1AndN_Solution(int n) { public int NumberOf1Between1AndN_Solution(int n)
{
int cnt = 0; int cnt = 0;
for (int m = 1; m <= n; m *= 10) { for (int m = 1; m <= n; m *= 10) {
int a = n / m, b = n % m; int a = n / m, b = n % m;
...@@ -1968,47 +1977,53 @@ public int NumberOf1Between1AndN_Solution(int n) { ...@@ -1968,47 +1977,53 @@ public int NumberOf1Between1AndN_Solution(int n) {
## 解题思路 ## 解题思路
```java ```java
public int digitAtIndex(int index) { public int getDigitAtIndex(int index)
{
if (index < 0) if (index < 0)
return -1; return -1;
int digit = 1; int place = 1; // 位数,1 表示个位,2 表示 十位...
while (true) { while (true) {
int amount = getAmountOfDigit(digit); int amount = getAmountOfPlace(place);
int totalAmount = amount * digit; int totalAmount = amount * place;
if (index < totalAmount) if (index < totalAmount)
return digitAtIndex(index, digit); return getDigitAtIndex(index, place);
index -= totalAmount; index -= totalAmount;
digit++; place++;
} }
} }
/** /**
* digit 位数的数字组成的字符串长度 * place 位数的数字组成的字符串长度
* 例如 digit = 2,return 90 * 10, 90, 900, ...
*/ */
private int getAmountOfDigit(int digit) { private int getAmountOfPlace(int place)
if (digit == 1) {
if (place == 1)
return 10; return 10;
return (int) Math.pow(10, digit - 1) * 9; return (int) Math.pow(10, place - 1) * 9;
} }
/** /**
* 在 digit 位数组成的字符串中,第 index 个数 * place 位数的起始数字
* 0, 10, 100, ...
*/ */
private int digitAtIndex(int index, int digit) { private int getBeginNumberOfPlace(int place)
int number = beginNumber(digit) + index / digit; {
int remain = index % digit; if (place == 1)
return (number + "").charAt(remain) - '0'; return 0;
return (int) Math.pow(10, place - 1);
} }
/** /**
* digit 位数的起始数字 * 在 place 位数组成的字符串中,第 index 个数
* 例如 digit = 2 return 10
*/ */
private int beginNumber(int digit) { private int getDigitAtIndex(int index, int place)
if (digit == 1) {
return 0; int beginNumber = getBeginNumberOfPlace(place);
return (int) Math.pow(10, digit - 1); int shiftNumber = index / place;
String number = (beginNumber + shiftNumber) + "";
int count = index % place;
return number.charAt(count) - '0';
} }
``` ```
......
...@@ -568,7 +568,7 @@ BGP 只能寻找一条比较好的路由,而不是最佳路由。 ...@@ -568,7 +568,7 @@ BGP 只能寻找一条比较好的路由,而不是最佳路由。
# 五、运输层* # 五、运输层*
网络层只把分组发送到目的主机,但是真正通信的并不是主机而是主机中的进程。运输层提供了进程间的逻辑通信,运输层向高层用户屏蔽了下面网络层的核心细节,使应用程序看见的好像在两个运输层实体之间有一条端到端的逻辑通信信道。 网络层只把分组发送到目的主机,但是真正通信的并不是主机而是主机中的进程。运输层提供了进程间的逻辑通信,运输层向高层用户屏蔽了下面网络层的核心细节,使应用程序看起来像是在两个运输层实体之间有一条端到端的逻辑通信信道。
## UDP 和 TCP 的特点 ## UDP 和 TCP 的特点
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册