Ricadro


  • 首页

  • 标签

  • 分类

  • 归档

  • 关于

斐波那契数列

发表于 2019-02-25 | 分类于 剑指offer | | 阅读次数:
字数统计: 252字 | 阅读时长 ≈ 1分钟

题目描述

大家都知道斐波那契数列,现在要求输入一个整数n,请你输出斐波那契数列的第n项(从0开始,第0项为0)。n<=39

  • 斐波那契数列指的是这样一个数列 1, 1, 2, 3, 5, 8, 13, 21, 34, 55, 89, 144, 233,377,610,987,1597,2584,4181,6765,10946,17711,28657,46368……..
  • 这个数列从第3项开始,每一项都等于前两项之和。

解题思路

  • f(n) = f(n-1) + f(n-2); f(n-1) = f(n-2) + f(n-3) 初步想法是使用递归,但是这样会有重复计算的问题(f(n-2)重复计算)。
  • 由于第n项只与第n-1项与第n-2项有关,所以只计算前两项的结果再重新赋值计算即可。
阅读全文 »

旋转数组中的最小数字

发表于 2019-02-24 | 分类于 剑指offer | | 阅读次数:
字数统计: 216字 | 阅读时长 ≈ 1分钟

题目描述

把一个数组最开始的若干个元素搬到数组的末尾,我们称之为数组的旋转。 输入一个非减排序的数组的一个旋转,输出旋转数组的最小元素。 例如数组{3,4,5,1,2}为{1,2,3,4,5}的一个旋转,该数组的最小值为1。 NOTE:给出的所有元素都大于0,若数组大小为0,请返回0。

解题思路

  • 该数组为非减排序数组的旋转,需要找到该数组的最小元素,可采用二分查找法。
阅读全文 »

用两个栈实现队列

发表于 2019-02-24 | 分类于 剑指offer | | 阅读次数:
字数统计: 126字 | 阅读时长 ≈ 1分钟

题目描述

用两个栈来实现一个队列,完成队列的Push和Pop操作。 队列中的元素为int类型。

解题思路

使元素先push入A栈,再pop到B栈,再由B栈pop出,则实现队列先进先出。

阅读全文 »

重建二叉树

发表于 2019-02-24 | 分类于 剑指offer | | 阅读次数:
字数统计: 689字 | 阅读时长 ≈ 2分钟

题目描述

输入某二叉树的前序遍历和中序遍历的结果,请重建出该二叉树。假设输入的前序遍历和中序遍历的结果中都不含重复的数字。例如输入前序遍历序列{1,2,4,7,3,5,6,8}和中序遍历序列{4,7,2,1,5,3,8,6},则重建二叉树并返回。

解题思路

  • root最简单,前序遍历序列{1,2,4,7,3,5,6,8}的第一节点1就是root。
  • 中序遍历序列{4,7,2,1,5,3,8,6} 其中root节点1左侧的4,7,2必然是root的左子树,1右侧的5,3,8,6必然是root的右子树。
  • 观察左子树4,7,2,左子树的中的根节点必然是大树的root的leftchild。在前序遍历中,大树的root的leftchild位于root之后,所以左子树的根节点为2。
  • 同样的道理,root的右子树节点5,3,8,6中的根节点也可以通过前序遍历求得。在前序遍历中,一定是先把root和root的所有左子树节点遍历完之后才会遍历右子树,并且遍历的右子树的第一个节点就是右子树的根节点。
  • 中序遍历中,root左侧是4,7,2,所以有3个节点位于root左侧。那么在前序遍历中,必然是第1个是1,第2到第4个由4,7,2组成,第5个就是root的右子树的根节点了,是3。
  • 观察发现,上面的过程是递归的。先找到当前树的根节点,然后划分为左子树,右子树,然后进入左子树重复上面的过程,然后进入右子树重复上面的过程。最后就可以还原一棵树了。
阅读全文 »

从尾到头打印链表

发表于 2019-02-23 | 分类于 剑指offer | | 阅读次数:
字数统计: 139字 | 阅读时长 ≈ 1分钟

题目描述

输入一个链表,按链表值从尾到头的顺序返回一个ArrayList。

解题思路

由于需要从尾到头打印,可以栈后进先出(LIFO)来解决这道题。

阅读全文 »

替换空格

发表于 2019-02-23 | 分类于 剑指offer | | 阅读次数:
字数统计: 238字 | 阅读时长 ≈ 1分钟

题目描述

请实现一个函数,将一个字符串中的每个空格替换成“%20”。例如,当字符串为We Are Happy.则经过替换之后的字符串为We%20Are%20Happy。

解题思路

由于每个空格替换成“%20”,则替换掉一个空格之后数组长度加2,然后倒序复制前数组即可。要注意⚠️数组长度,否则会出现数组越界的情况。

阅读全文 »

二维数组中的查找

发表于 2019-02-23 | 分类于 剑指offer | | 阅读次数:
字数统计: 281字 | 阅读时长 ≈ 1分钟

题目描述

在一个二维数组中(每个一维数组的长度相同),每一行都按照从左到右递增的顺序排序,每一列都按照从上到下递增的顺序排序。请完成一个函数,输入这样的一个二维数组和一个整数,判断数组中是否含有该整数。

解题思路

由于此数组每一行从左到右递增,每一列从上到下递增,所以可以根据右上角的数X来和target比较。

  • 如target比X大,则target不在X所在这行,需要往下移一行,可以缩小区间。
  • 如target比X小,则target不在X所在这列,需要往左移一列。
  • 如target=X,则含有该整数
阅读全文 »

HttpUtils

发表于 2019-02-22 | 分类于 常用工具 | | 阅读次数:
字数统计: 1.9k字 | 阅读时长 ≈ 10分钟

Http请求工具类

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
import org.apache.http.HttpHeaders;
import org.apache.http.HttpHost;
import org.apache.http.HttpResponse;
import org.apache.http.NameValuePair;
import org.apache.http.client.config.RequestConfig;
import org.apache.http.client.config.RequestConfig.Builder;
import org.apache.http.client.entity.UrlEncodedFormEntity;
import org.apache.http.client.methods.*;
import org.apache.http.conn.ssl.SSLConnectionSocketFactory;
import org.apache.http.conn.ssl.SSLContextBuilder;
import org.apache.http.conn.ssl.TrustStrategy;
import org.apache.http.entity.StringEntity;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.impl.client.HttpClientBuilder;
import org.apache.http.impl.client.StandardHttpRequestRetryHandler;
import org.apache.http.message.BasicNameValuePair;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.net.URLEncoder;
import java.security.cert.CertificateException;
import java.security.cert.X509Certificate;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.function.BiConsumer;
import java.util.stream.IntStream;

/**
* Http请求工具类
*
* @Author: ricadro
* @Date: 2018/12/18 17:05
*/
public final class HttpUtils {

/**
* GET 请求, 兼容 HTTP 和 HTTPS 请求
*
* @param url 请求的地址
* @return {@link HttpRequest}
*/
public static HttpRequest get(String url) {
return new HttpRequest(url, RequestMethod.GET);
}

/**
* PUT 请求, 兼容 HTTP 和 HTTPS 请求
*
* @param url 请求的地址
* @return {@link HttpRequest}
*/
public static HttpRequest put(String url) {
return new HttpRequest(url, RequestMethod.PUT);
}

/**
* POST 请求, 兼容 HTTP 和 HTTPS 请求
*
* @param url 请求的地址
* @return {@link HttpRequest}
*/
public static HttpRequest post(String url) {
return new HttpRequest(url, RequestMethod.POST);
}

/**
* DELETE 请求, 兼容 HTTP 和 HTTPS 请求
*
* @param url 请求的地址
* @return {@link HttpRequest}
*/
public static HttpRequest delete(String url) {
return new HttpRequest(url, RequestMethod.DELETE);
}

/**
* 支持的请求方法
*
* @author fanlychie
*/
private enum RequestMethod {
GET, POST, PUT, DELETE
}

/**
* 封装 HTTP 请求参数和操作
*
* @author fanlychie
*/
public final static class HttpRequest {

/**
* 请求的地址
*/
private String url;

// 请求体内容
private String body;

// 请求方法
private RequestMethod method;

// 失败重试的次数
private int retryTimes = 3;

// 读取结果超时的秒数
private int readTimeoutSecond = 120;

// 连接服务超时的秒数
private int connectTimeoutSecond = 60;

// 读取结果使用的字符集编码
private String readResultCharset = "UTF-8";

// 请求参数
private Map<String, String> params;

// 请求头参数
private Map<String, String> header;

// 代理端口
private int proxyPort;

// 代理主机
private String proxyHost;

// 代理类型(http或https)
private String proxySchema;

private HttpRequest(String url, RequestMethod method) {
this.url = url;
this.method = method;
}

/**
* 执行请求
*
* @param consumer (请求结果的状态码, 请求结果的文本内容)
*/
public void execute(BiConsumer<Integer, String> consumer) {
try {
doService(consumer);
} catch (Exception e) {
throw new RuntimeException(e);
}
}

/**
* 设置请求体, JSON 参数可设于此域
*
* @param body 请求体内容
* @return {@link HttpRequest}
*/
public HttpRequest setBody(String body) {
this.body = body;
return this;
}

/**
* 设置失败重试的次数, 默认值 0
*
* @param retryTimes 失败重试的次数
* @return {@link HttpRequest}
*/
public HttpRequest setRetryTimes(int retryTimes) {
this.retryTimes = retryTimes;
return this;
}

/**
* 设置读取结果超时的秒数, 默认 120s
*
* @param readTimeoutSecond 读取结果超时的秒
* @return {@link HttpRequest}
*/
public HttpRequest setReadTimeoutSecond(int readTimeoutSecond) {
this.readTimeoutSecond = readTimeoutSecond;
return this;
}

/**
* 设置连接服务超时的秒数, 默认 60s
*
* @param connectTimeoutSecond 连接服务超时的秒数
* @return {@link HttpRequest}
*/
public HttpRequest setConnectTimeoutSecond(int connectTimeoutSecond) {
this.connectTimeoutSecond = connectTimeoutSecond;
return this;
}

/**
* 设置请求参数表
*
* @param params 请求参数表
* @return {@link HttpRequest}
*/
@SuppressWarnings({"rawtypes"})
public HttpRequest setParams(Map params) {
this.params = convertMap(params);
return this;
}

/**
* 设置请求头参数表
*
* @param header 请求头参数表
* @return {@link HttpRequest}
*/
@SuppressWarnings({"rawtypes"})
public HttpRequest setHeader(Map header) {
this.header = convertMap(header);
return this;
}

/**
* 设置请求参数键值对
*
* @param nameValues 请求参数键值对
* @return {@link HttpRequest}
*/
public HttpRequest setParams(Object... nameValues) {
this.params = convertMap(nameValues);
return this;
}

/**
* 设置请求头参数键值对
*
* @param nameValues 请求头参数键值对
* @return {@link HttpRequest}
*/
public HttpRequest setHeader(String... nameValues) {
this.header = convertMap(nameValues);
return this;
}

/**
* 添加请求参数
*
* @param name 参数名
* @param value 参数值
* @return
*/
public HttpRequest addParam(String name, Object value) {
if (this.params == null) {
this.params = new HashMap<>();
}
params.put(name, value.toString());
return this;
}

/**
* 添加请求头参数
*
* @param name 参数名
* @param value 参数值
* @return
*/
public HttpRequest addHeader(String name, Object value) {
if (this.header == null) {
this.header = new HashMap<>();
}
header.put(name, value.toString());
return this;
}

/**
* 设置代理
*
* @param host 代理主机
* @param port 代理端口
* @return {@link HttpRequest}
*/
public HttpRequest setProxy(String host, int port) {
return setProxy(host, port, "http");
}

/**
* 设置代理
*
* @param host 代理主机
* @param port 代理端口
* @param schema 代理类型(http或https), 默认 http
* @return {@link HttpRequest}
*/
public HttpRequest setProxy(String host, int port, String schema) {
this.proxyHost = host;
this.proxyPort = port;
this.proxySchema = schema;
return this;
}

/**
* 设置读取结果使用的字符集编码
*
* @param readResultCharset 读取结果使用的字符集编码, 默认 UTF-8
* @return {@link HttpRequest}
*/
public HttpRequest setReadResultCharset(String readResultCharset) {
this.readResultCharset = readResultCharset;
return this;
}

/**
* 执行请求
*
* @param consumer BiConsumer
* @throws Exception
*/
private void doService(BiConsumer<Integer, String> consumer) throws Exception {
try (CloseableHttpClient client = getHttpClient()) {
HttpUriRequest request = getHttpUriRequest();
// 执行请求
HttpResponse response = client.execute(request);
// 状态码
int statusCode = response.getStatusLine().getStatusCode();
// 响应内容
String responseText = readStream(response.getEntity().getContent());
// Consumer
consumer.accept(statusCode, responseText);
}
}

/**
* 转换参数为散列表
*
* @param obj 被转换的参数
* @return Map
*/
private Map<String, String> convertMap(Object obj) {
Map<String, String> target = new HashMap<>();
if (obj instanceof Map) {
Map<?, ?> map = (Map<?, ?>) obj;
map.forEach((k, v) -> target.put(k.toString(), v.toString()));
} else if (obj.getClass().isArray()) {
Object[] array = (Object[]) obj;
IntStream.range(0, array.length).filter((i) -> i % 2 == 0)
.forEach((i) -> target.put(array[i].toString(), array[i + 1].toString()));
}
return target;
}

/**
* 构建 HttpUriRequest
*
* @param base HttpUriRequest
* @return HttpUriRequest
*/
private HttpUriRequest buildHttpUriRequest(HttpUriRequest base) {
if (header != null && !header.isEmpty()) {
header.forEach((k, v) -> base.addHeader(k, v));
}
return base;
}

/**
* 构建 HttpUriRequest
*
* @param base HttpEntityEnclosingRequestBase
* @return HttpUriRequest
* @throws Exception
*/
private HttpUriRequest buildHttpUriRequest(HttpEntityEnclosingRequestBase base) throws Exception {
if (header == null) {
header = new HashMap<>();
}
// 处理请求参数
if (params != null && !params.isEmpty()) {
// 参数键值对数组
List<NameValuePair> nameValuePairs = new ArrayList<>();
params.forEach((k, v) -> nameValuePairs.add(new BasicNameValuePair(k, v)));
// 如果有参数, 设置请求参数
if (!nameValuePairs.isEmpty()) {
base.setEntity(new UrlEncodedFormEntity(nameValuePairs, "UTF-8"));
header.put(HttpHeaders.CONTENT_TYPE, "application/x-www-form-urlencoded; charset=utf-8");
}
}
// 处理请求参数
else if (body != null && !body.isEmpty()) {
base.setEntity(new StringEntity(body, "UTF-8"));
header.put(HttpHeaders.ACCEPT, "application/json");
header.put(HttpHeaders.CONTENT_TYPE, "application/json; charset=utf-8");
}
return buildHttpUriRequest((HttpUriRequest) base);
}

/**
* 构建 HttpUriRequest
*
* @return HttpUriRequest
* @throws Exception
*/
private HttpUriRequest buildHttpUriRequest() throws Exception {
if (params != null && !params.isEmpty()) {
StringBuilder paramStr = new StringBuilder();
params.forEach((k, v) -> {
if (paramStr.length() > 0) {
paramStr.append("&");
}
paramStr.append(k).append("=").append(encode(v));
});
if (paramStr.length() > 0) {
if (url.contains("?")) {
url += "&" + paramStr;
} else {
url += "?" + paramStr;
}
}
}
return buildHttpUriRequest(RequestBuilder.get().setUri(url).build());
}

/**
* 获取 HttpUriRequest 对象
*
* @return HttpUriRequest
* @throws Exception
*/
private HttpUriRequest getHttpUriRequest() throws Exception {
switch (method) {
case GET:
return buildHttpUriRequest();
case PUT:
return buildHttpUriRequest(new HttpPut(url));
case POST:
return buildHttpUriRequest(new HttpPost(url));
case DELETE:
return buildHttpUriRequest(new HttpDelete(url));
default:
throw new UnsupportedOperationException("Unsupport " + method + " request.");
}
}

/**
* 编码字符串
*
* @param str 源字串
* @return 返回UTF-8编码的内容
*/
private String encode(String str) {
try {
return URLEncoder.encode(str, "UTF-8");
} catch (Exception e) {
throw new RuntimeException(e);
}
}

/**
* 读取流内容
*
* @param inStream 输入流
* @return
* @throws IOException
*/
private String readStream(InputStream inStream) throws Exception {
try (BufferedReader reader = new BufferedReader(new InputStreamReader(inStream, readResultCharset))) {
String tempStr = null;
StringBuilder builder = new StringBuilder();
while ((tempStr = reader.readLine()) != null) {
builder.append(tempStr);
}
return builder.toString();
}
}

/**
* 获取客户端请求对象
*
* @return CloseableHttpClient
* @throws Exception
*/
private CloseableHttpClient getHttpClient() throws Exception {
Builder requestConfigBuilder = RequestConfig.custom()
// 设置连接超时
.setConnectTimeout(connectTimeoutSecond * 1000)
// 设置读取超时
.setSocketTimeout(readTimeoutSecond * 1000);
// 设置代理
if (proxyHost != null && !proxyHost.isEmpty() && proxyPort > 0) {
requestConfigBuilder.setProxy(new HttpHost(proxyHost, proxyPort, proxySchema));
}
HttpClientBuilder builder = HttpClientBuilder.create()
// 设置请求配置
.setDefaultRequestConfig(requestConfigBuilder.build())
// 设置失败重试
.setRetryHandler(new StandardHttpRequestRetryHandler(retryTimes, true));
// 是否使用SSL协议链接
if (url.startsWith("https")) {
builder.setSSLSocketFactory(new SSLConnectionSocketFactory(
new SSLContextBuilder().loadTrustMaterial(null, new TrustStrategy() {
// 信任所有
@Override
public boolean isTrusted(X509Certificate[] chain, String authType)
throws CertificateException {
return true;
}
}).build()));
}
return builder.build();
}

}
}

使用方法

1
2
3
4
5
6
7
8
9
10
11
12
13
@Test
public void test() {
String url = "http://xxx.com";
Map<String, Object> params = new HashMap<>();
params.put("xxx", "xxx");
HttpUtils.get(url).setParams(params).execute((status, response) -> {
if (status == 200){
System.out.println(response);
}else {
System.out.println("请求失败");
}
});
}

App热更新

发表于 2019-02-22 | 分类于 疑难杂症 | | 阅读次数:
字数统计: 319字 | 阅读时长 ≈ 1分钟

问题描述

使用微软的code-push部署app热更新时,遇到了这样一个问题,由于需要在热更新时,做一个进度条来提示用户更新进度,所以需要拿到下载时的成功回调,这个回调会有以下两个值。

1
2
3
export interface DownloadProgress {
totalBytes: number;
receivedBytes: number;

两个值相除即为下载进度,但是问题出现了!在演练环境一切正常,在生产环境时totalBytes=0,导致没有进度条的变化。

阅读全文 »

Tomcat缓存问题

发表于 2019-01-24 | 分类于 日常问题 | | 阅读次数:
字数统计: 242字 | 阅读时长 ≈ 1分钟

问题描述

最近在开发后台管理系统的时候,遇到这样一个问题,将改好的jsp文件直接上传到服务器上,并把同一文件替换掉,发现页面效果没有生效,
重启tomcat也没有效果。

阅读全文 »
1…34

ricadro

40 日志
7 分类
11 标签
GitHub E-Mail
© 2020 ricadro | Site words total count: 15.1k
由 Hexo 强力驱动
|
主题 — NexT.Muse v5.1.4