Skip to content
体验新版
项目
组织
正在加载...
登录
切换导航
打开侧边栏
Coudy Hou
JavaGuide
提交
63cca039
J
JavaGuide
项目概览
Coudy Hou
/
JavaGuide
与 Fork 源项目一致
从无法访问的项目Fork
通知
5
Star
0
Fork
0
代码
文件
提交
分支
Tags
贡献者
分支图
Diff
Issue
0
列表
看板
标记
里程碑
合并请求
0
Wiki
0
Wiki
分析
仓库
DevOps
项目成员
Pages
J
JavaGuide
项目概览
项目概览
详情
发布
仓库
仓库
文件
提交
分支
标签
贡献者
分支图
比较
Issue
0
Issue
0
列表
看板
标记
里程碑
合并请求
0
合并请求
0
Pages
分析
分析
仓库分析
DevOps
Wiki
0
Wiki
成员
成员
收起侧边栏
关闭侧边栏
动态
分支图
创建新Issue
提交
Issue看板
前往新版Gitcode,体验更适合开发者的 AI 搜索 >>
提交
63cca039
编写于
3月 26, 2019
作者:
S
SnailClimb
浏览文件
操作
浏览文件
下载
电子邮件补丁
差异文件
Update 对算法部分进行大幅度更新
上级
7f506299
变更
28
展开全部
隐藏空白更改
内联
并排
Showing
28 changed file
with
72 addition
and
1558 deletion
+72
-1558
docs/dataStructures-algorithms/source code/securityAlgorithm/.classpath
...tures-algorithms/source code/securityAlgorithm/.classpath
+0
-26
docs/dataStructures-algorithms/source code/securityAlgorithm/.gitignore
...tures-algorithms/source code/securityAlgorithm/.gitignore
+0
-1
docs/dataStructures-algorithms/source code/securityAlgorithm/.project
...uctures-algorithms/source code/securityAlgorithm/.project
+0
-23
docs/dataStructures-algorithms/source code/securityAlgorithm/.settings/org.eclipse.core.resources.prefs
...urityAlgorithm/.settings/org.eclipse.core.resources.prefs
+0
-4
docs/dataStructures-algorithms/source code/securityAlgorithm/.settings/org.eclipse.jdt.core.prefs
...de/securityAlgorithm/.settings/org.eclipse.jdt.core.prefs
+0
-5
docs/dataStructures-algorithms/source code/securityAlgorithm/.settings/org.eclipse.m2e.core.prefs
...de/securityAlgorithm/.settings/org.eclipse.m2e.core.prefs
+0
-4
docs/dataStructures-algorithms/source code/securityAlgorithm/pom.xml
...ructures-algorithms/source code/securityAlgorithm/pom.xml
+0
-37
docs/dataStructures-algorithms/source code/securityAlgorithm/src/main/java/com/snailclimb/ks/securityAlgorithm/Base64Demo.java
.../java/com/snailclimb/ks/securityAlgorithm/Base64Demo.java
+0
-49
docs/dataStructures-algorithms/source code/securityAlgorithm/src/main/java/com/snailclimb/ks/securityAlgorithm/DesDemo.java
...ain/java/com/snailclimb/ks/securityAlgorithm/DesDemo.java
+0
-100
docs/dataStructures-algorithms/source code/securityAlgorithm/src/main/java/com/snailclimb/ks/securityAlgorithm/IDEADemo.java
...in/java/com/snailclimb/ks/securityAlgorithm/IDEADemo.java
+0
-46
docs/dataStructures-algorithms/source code/securityAlgorithm/src/main/java/com/snailclimb/ks/securityAlgorithm/MD5.java
...rc/main/java/com/snailclimb/ks/securityAlgorithm/MD5.java
+0
-160
docs/dataStructures-algorithms/source code/securityAlgorithm/src/main/java/com/snailclimb/ks/securityAlgorithm/MD5Demo.java
...ain/java/com/snailclimb/ks/securityAlgorithm/MD5Demo.java
+0
-50
docs/dataStructures-algorithms/source code/securityAlgorithm/src/main/java/com/snailclimb/ks/securityAlgorithm/RSADemo.java
...ain/java/com/snailclimb/ks/securityAlgorithm/RSADemo.java
+0
-249
docs/dataStructures-algorithms/source code/securityAlgorithm/src/main/java/com/snailclimb/ks/securityAlgorithm/SHA1Demo.java
...in/java/com/snailclimb/ks/securityAlgorithm/SHA1Demo.java
+0
-45
docs/dataStructures-algorithms/source code/securityAlgorithm/src/main/java/com/snailclimb/ks/securityAlgorithm/readme
.../src/main/java/com/snailclimb/ks/securityAlgorithm/readme
+0
-3
docs/dataStructures-algorithms/source code/securityAlgorithm/src/test/java/com/snailclimb/ks/securityAlgorithm/AppTest.java
...est/java/com/snailclimb/ks/securityAlgorithm/AppTest.java
+0
-38
docs/dataStructures-algorithms/公司真题.md
docs/dataStructures-algorithms/公司真题.md
+20
-22
docs/dataStructures-algorithms/几道常见的子符串算法题.md
docs/dataStructures-algorithms/几道常见的子符串算法题.md
+0
-0
docs/dataStructures-algorithms/几道常见的链表算法题.md
docs/dataStructures-algorithms/几道常见的链表算法题.md
+0
-0
docs/dataStructures-algorithms/剑指offer部分编程题.md
docs/dataStructures-algorithms/剑指offer部分编程题.md
+0
-0
docs/dataStructures-algorithms/常见安全算法(MD5、SHA1、Base64等等)总结.md
.../dataStructures-algorithms/常见安全算法(MD5、SHA1、Base64等等)总结.md
+0
-0
docs/dataStructures-algorithms/算法.md
docs/dataStructures-algorithms/算法.md
+0
-90
docs/dataStructures-algorithms/算法学习资源推荐.md
docs/dataStructures-algorithms/算法学习资源推荐.md
+52
-0
docs/dataStructures-algorithms/算法题解析/剑指offer/(1)斐波那契数列问题和跳台阶问题.md
...aStructures-algorithms/算法题解析/剑指offer/(1)斐波那契数列问题和跳台阶问题.md
+0
-127
docs/dataStructures-algorithms/算法题解析/剑指offer/(2)二维数组查找和替换空格问题.md
...taStructures-algorithms/算法题解析/剑指offer/(2)二维数组查找和替换空格问题.md
+0
-64
docs/dataStructures-algorithms/算法题解析/剑指offer/(3)数值的整数次方和调整数组元素顺序.md
...tructures-algorithms/算法题解析/剑指offer/(3)数值的整数次方和调整数组元素顺序.md
+0
-113
docs/dataStructures-algorithms/算法题解析/剑指offer/(4)链表相关编程题.md
docs/dataStructures-algorithms/算法题解析/剑指offer/(4)链表相关编程题.md
+0
-190
docs/dataStructures-algorithms/算法题解析/剑指offer/(5)栈变队列和栈的压入、弹出序列.md
...aStructures-algorithms/算法题解析/剑指offer/(5)栈变队列和栈的压入、弹出序列.md
+0
-112
未找到文件。
docs/dataStructures-algorithms/source code/securityAlgorithm/.classpath
已删除
100644 → 0
浏览文件 @
7f506299
<?xml version="1.0" encoding="UTF-8"?>
<classpath>
<classpathentry
kind=
"src"
output=
"target/classes"
path=
"src/main/java"
>
<attributes>
<attribute
name=
"optional"
value=
"true"
/>
<attribute
name=
"maven.pomderived"
value=
"true"
/>
</attributes>
</classpathentry>
<classpathentry
kind=
"src"
output=
"target/test-classes"
path=
"src/test/java"
>
<attributes>
<attribute
name=
"optional"
value=
"true"
/>
<attribute
name=
"maven.pomderived"
value=
"true"
/>
</attributes>
</classpathentry>
<classpathentry
kind=
"con"
path=
"org.eclipse.jdt.launching.JRE_CONTAINER/org.eclipse.jdt.internal.debug.ui.launcher.StandardVMType/J2SE-1.5"
>
<attributes>
<attribute
name=
"maven.pomderived"
value=
"true"
/>
</attributes>
</classpathentry>
<classpathentry
kind=
"con"
path=
"org.eclipse.m2e.MAVEN2_CLASSPATH_CONTAINER"
>
<attributes>
<attribute
name=
"maven.pomderived"
value=
"true"
/>
</attributes>
</classpathentry>
<classpathentry
kind=
"output"
path=
"target/classes"
/>
</classpath>
docs/dataStructures-algorithms/source code/securityAlgorithm/.gitignore
已删除
100644 → 0
浏览文件 @
7f506299
/target/
docs/dataStructures-algorithms/source code/securityAlgorithm/.project
已删除
100644 → 0
浏览文件 @
7f506299
<?xml version="1.0" encoding="UTF-8"?>
<projectDescription>
<name>
securityAlgorithm
</name>
<comment></comment>
<projects>
</projects>
<buildSpec>
<buildCommand>
<name>
org.eclipse.jdt.core.javabuilder
</name>
<arguments>
</arguments>
</buildCommand>
<buildCommand>
<name>
org.eclipse.m2e.core.maven2Builder
</name>
<arguments>
</arguments>
</buildCommand>
</buildSpec>
<natures>
<nature>
org.eclipse.jdt.core.javanature
</nature>
<nature>
org.eclipse.m2e.core.maven2Nature
</nature>
</natures>
</projectDescription>
docs/dataStructures-algorithms/source code/securityAlgorithm/.settings/org.eclipse.core.resources.prefs
已删除
100644 → 0
浏览文件 @
7f506299
eclipse.preferences.version=1
encoding//src/main/java=UTF-8
encoding//src/test/java=UTF-8
encoding/<project>=UTF-8
docs/dataStructures-algorithms/source code/securityAlgorithm/.settings/org.eclipse.jdt.core.prefs
已删除
100644 → 0
浏览文件 @
7f506299
eclipse.preferences.version=1
org.eclipse.jdt.core.compiler.codegen.targetPlatform=1.5
org.eclipse.jdt.core.compiler.compliance=1.5
org.eclipse.jdt.core.compiler.problem.forbiddenReference=warning
org.eclipse.jdt.core.compiler.source=1.5
docs/dataStructures-algorithms/source code/securityAlgorithm/.settings/org.eclipse.m2e.core.prefs
已删除
100644 → 0
浏览文件 @
7f506299
activeProfiles=
eclipse.preferences.version=1
resolveWorkspaceProjects=true
version=1
docs/dataStructures-algorithms/source code/securityAlgorithm/pom.xml
已删除
100644 → 0
浏览文件 @
7f506299
<project
xmlns=
"http://maven.apache.org/POM/4.0.0"
xmlns:xsi=
"http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation=
"http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"
>
<modelVersion>
4.0.0
</modelVersion>
<groupId>
com.snailclimb.ks
</groupId>
<artifactId>
securityAlgorithm
</artifactId>
<version>
0.0.1-SNAPSHOT
</version>
<packaging>
jar
</packaging>
<name>
securityAlgorithm
</name>
<url>
http://maven.apache.org
</url>
<properties>
<project.build.sourceEncoding>
UTF-8
</project.build.sourceEncoding>
</properties>
<dependencies>
<dependency>
<groupId>
junit
</groupId>
<artifactId>
junit
</artifactId>
<version>
4.12
</version>
<scope>
test
</scope>
</dependency>
<!-- Base64 -->
<dependency>
<groupId>
commons-codec
</groupId>
<artifactId>
commons-codec
</artifactId>
<version>
1.8
</version>
</dependency>
<dependency>
<groupId>
org.bouncycastle
</groupId>
<artifactId>
bcprov-jdk15on
</artifactId>
<version>
1.56
</version>
</dependency>
</dependencies>
</project>
docs/dataStructures-algorithms/source code/securityAlgorithm/src/main/java/com/snailclimb/ks/securityAlgorithm/Base64Demo.java
已删除
100644 → 0
浏览文件 @
7f506299
package
com.snailclimb.ks.securityAlgorithm
;
import
java.io.UnsupportedEncodingException
;
import
java.util.Base64
;
public
class
Base64Demo
{
public
static
void
main
(
String
[]
args
)
throws
UnsupportedEncodingException
{
// TODO Auto-generated method stub
CommonsCodecDemo
();
bouncyCastleDemo
();
jdkDemo
();
}
static
String
str
=
"你若安好,便是晴天"
;
/**
* commons codec实现Base64加密解密
*/
public
static
void
CommonsCodecDemo
()
{
// 加密:
byte
[]
encodeBytes
=
org
.
apache
.
commons
.
codec
.
binary
.
Base64
.
encodeBase64
(
str
.
getBytes
());
System
.
out
.
println
(
"commons codec实现base64加密: "
+
new
String
(
encodeBytes
));
// 解密:
byte
[]
decodeBytes
=
org
.
apache
.
commons
.
codec
.
binary
.
Base64
.
decodeBase64
(
encodeBytes
);
System
.
out
.
println
(
"commons codec实现base64解密: "
+
new
String
(
decodeBytes
));
}
/**
* bouncy castle实现Base64加密解密
*/
public
static
void
bouncyCastleDemo
()
{
// 加密
byte
[]
encodeBytes
=
org
.
bouncycastle
.
util
.
encoders
.
Base64
.
encode
(
str
.
getBytes
());
System
.
out
.
println
(
"bouncy castle实现base64加密: "
+
new
String
(
encodeBytes
));
// 解密
byte
[]
decodeBytes
=
org
.
bouncycastle
.
util
.
encoders
.
Base64
.
decode
(
encodeBytes
);
System
.
out
.
println
(
"bouncy castle实现base64解密:"
+
new
String
(
decodeBytes
));
}
public
static
void
jdkDemo
()
throws
UnsupportedEncodingException
{
// 加密
String
encodeBytes
=
Base64
.
getEncoder
().
encodeToString
(
str
.
getBytes
(
"UTF-8"
));
System
.
out
.
println
(
"JDK实现的base64加密: "
+
encodeBytes
);
//解密
byte
[]
decodeBytes
=
Base64
.
getDecoder
().
decode
(
encodeBytes
.
getBytes
(
"UTF-8"
));
System
.
out
.
println
(
"JDK实现的base64解密: "
+
new
String
(
decodeBytes
));
}
}
docs/dataStructures-algorithms/source code/securityAlgorithm/src/main/java/com/snailclimb/ks/securityAlgorithm/DesDemo.java
已删除
100644 → 0
浏览文件 @
7f506299
package
com.snailclimb.ks.securityAlgorithm
;
import
java.io.UnsupportedEncodingException
;
import
java.security.SecureRandom
;
import
javax.crypto.spec.DESKeySpec
;
import
javax.crypto.SecretKeyFactory
;
import
javax.crypto.SecretKey
;
import
javax.crypto.Cipher
;
/**
* DES加密介绍 DES是一种对称加密算法,所谓对称加密算法即:加密和解密使用相同密钥的算法。DES加密算法出自IBM的研究,
* 后来被美国政府正式采用,之后开始广泛流传,但是近些年使用越来越少,因为DES使用56位密钥,以现代计算能力,
* 24小时内即可被破解。虽然如此,在某些简单应用中,我们还是可以使用DES加密算法,本文简单讲解DES的JAVA实现 。
* 注意:DES加密和解密过程中,密钥长度都必须是8的倍数
*/
public
class
DesDemo
{
public
DesDemo
()
{
}
// 测试
public
static
void
main
(
String
args
[])
{
// 待加密内容
String
str
=
"cryptology"
;
// 密码,长度要是8的倍数
String
password
=
"95880288"
;
byte
[]
result
;
try
{
result
=
DesDemo
.
encrypt
(
str
.
getBytes
(),
password
);
System
.
out
.
println
(
"加密后:"
+
result
);
byte
[]
decryResult
=
DesDemo
.
decrypt
(
result
,
password
);
System
.
out
.
println
(
"解密后:"
+
decryResult
);
}
catch
(
UnsupportedEncodingException
e2
)
{
// TODO Auto-generated catch block
e2
.
printStackTrace
();
}
catch
(
Exception
e1
)
{
e1
.
printStackTrace
();
}
}
// 直接将如上内容解密
/**
* 加密
*
* @param datasource
* byte[]
* @param password
* String
* @return byte[]
*/
public
static
byte
[]
encrypt
(
byte
[]
datasource
,
String
password
)
{
try
{
SecureRandom
random
=
new
SecureRandom
();
DESKeySpec
desKey
=
new
DESKeySpec
(
password
.
getBytes
());
// 创建一个密匙工厂,然后用它把DESKeySpec转换成
SecretKeyFactory
keyFactory
=
SecretKeyFactory
.
getInstance
(
"DES"
);
SecretKey
securekey
=
keyFactory
.
generateSecret
(
desKey
);
// Cipher对象实际完成加密操作
Cipher
cipher
=
Cipher
.
getInstance
(
"DES"
);
// 用密匙初始化Cipher对象,ENCRYPT_MODE用于将 Cipher 初始化为加密模式的常量
cipher
.
init
(
Cipher
.
ENCRYPT_MODE
,
securekey
,
random
);
// 现在,获取数据并加密
// 正式执行加密操作
return
cipher
.
doFinal
(
datasource
);
// 按单部分操作加密或解密数据,或者结束一个多部分操作
}
catch
(
Throwable
e
)
{
e
.
printStackTrace
();
}
return
null
;
}
/**
* 解密
*
* @param src
* byte[]
* @param password
* String
* @return byte[]
* @throws Exception
*/
public
static
byte
[]
decrypt
(
byte
[]
src
,
String
password
)
throws
Exception
{
// DES算法要求有一个可信任的随机数源
SecureRandom
random
=
new
SecureRandom
();
// 创建一个DESKeySpec对象
DESKeySpec
desKey
=
new
DESKeySpec
(
password
.
getBytes
());
// 创建一个密匙工厂
SecretKeyFactory
keyFactory
=
SecretKeyFactory
.
getInstance
(
"DES"
);
// 返回实现指定转换的
// Cipher
// 对象
// 将DESKeySpec对象转换成SecretKey对象
SecretKey
securekey
=
keyFactory
.
generateSecret
(
desKey
);
// Cipher对象实际完成解密操作
Cipher
cipher
=
Cipher
.
getInstance
(
"DES"
);
// 用密匙初始化Cipher对象
cipher
.
init
(
Cipher
.
DECRYPT_MODE
,
securekey
,
random
);
// 真正开始解密操作
return
cipher
.
doFinal
(
src
);
}
}
\ No newline at end of file
docs/dataStructures-algorithms/source code/securityAlgorithm/src/main/java/com/snailclimb/ks/securityAlgorithm/IDEADemo.java
已删除
100644 → 0
浏览文件 @
7f506299
package
com.snailclimb.ks.securityAlgorithm
;
import
java.security.Key
;
import
java.security.Security
;
import
javax.crypto.Cipher
;
import
javax.crypto.KeyGenerator
;
import
javax.crypto.SecretKey
;
import
javax.crypto.spec.SecretKeySpec
;
import
org.apache.commons.codec.binary.Base64
;
import
org.bouncycastle.jce.provider.BouncyCastleProvider
;
public
class
IDEADemo
{
public
static
void
main
(
String
args
[])
{
bcIDEA
();
}
public
static
void
bcIDEA
()
{
String
src
=
"www.xttblog.com security idea"
;
try
{
Security
.
addProvider
(
new
BouncyCastleProvider
());
//生成key
KeyGenerator
keyGenerator
=
KeyGenerator
.
getInstance
(
"IDEA"
);
keyGenerator
.
init
(
128
);
SecretKey
secretKey
=
keyGenerator
.
generateKey
();
byte
[]
keyBytes
=
secretKey
.
getEncoded
();
//转换密钥
Key
key
=
new
SecretKeySpec
(
keyBytes
,
"IDEA"
);
//加密
Cipher
cipher
=
Cipher
.
getInstance
(
"IDEA/ECB/ISO10126Padding"
);
cipher
.
init
(
Cipher
.
ENCRYPT_MODE
,
key
);
byte
[]
result
=
cipher
.
doFinal
(
src
.
getBytes
());
System
.
out
.
println
(
"bc idea encrypt : "
+
Base64
.
encodeBase64String
(
result
));
//解密
cipher
.
init
(
Cipher
.
DECRYPT_MODE
,
key
);
result
=
cipher
.
doFinal
(
result
);
System
.
out
.
println
(
"bc idea decrypt : "
+
new
String
(
result
));
}
catch
(
Exception
e
)
{
e
.
printStackTrace
();
}
}
}
docs/dataStructures-algorithms/source code/securityAlgorithm/src/main/java/com/snailclimb/ks/securityAlgorithm/MD5.java
已删除
100644 → 0
浏览文件 @
7f506299
package
com.snailclimb.ks.securityAlgorithm
;
public
class
MD5
{
/*
*四个链接变量
*/
private
final
int
A
=
0x67452301
;
private
final
int
B
=
0xefcdab89
;
private
final
int
C
=
0x98badcfe
;
private
final
int
D
=
0x10325476
;
/*
*ABCD的临时变量
*/
private
int
Atemp
,
Btemp
,
Ctemp
,
Dtemp
;
/*
*常量ti
*公式:floor(abs(sin(i+1))×(2pow32)
*/
private
final
int
K
[]={
0xd76aa478
,
0xe8c7b756
,
0x242070db
,
0xc1bdceee
,
0xf57c0faf
,
0x4787c62a
,
0xa8304613
,
0xfd469501
,
0x698098d8
,
0x8b44f7af
,
0xffff5bb1
,
0x895cd7be
,
0x6b901122
,
0xfd987193
,
0xa679438e
,
0x49b40821
,
0xf61e2562
,
0xc040b340
,
0x265e5a51
,
0xe9b6c7aa
,
0xd62f105d
,
0x02441453
,
0xd8a1e681
,
0xe7d3fbc8
,
0x21e1cde6
,
0xc33707d6
,
0xf4d50d87
,
0x455a14ed
,
0xa9e3e905
,
0xfcefa3f8
,
0x676f02d9
,
0x8d2a4c8a
,
0xfffa3942
,
0x8771f681
,
0x6d9d6122
,
0xfde5380c
,
0xa4beea44
,
0x4bdecfa9
,
0xf6bb4b60
,
0xbebfbc70
,
0x289b7ec6
,
0xeaa127fa
,
0xd4ef3085
,
0x04881d05
,
0xd9d4d039
,
0xe6db99e5
,
0x1fa27cf8
,
0xc4ac5665
,
0xf4292244
,
0x432aff97
,
0xab9423a7
,
0xfc93a039
,
0x655b59c3
,
0x8f0ccc92
,
0xffeff47d
,
0x85845dd1
,
0x6fa87e4f
,
0xfe2ce6e0
,
0xa3014314
,
0x4e0811a1
,
0xf7537e82
,
0xbd3af235
,
0x2ad7d2bb
,
0xeb86d391
};
/*
*向左位移数,计算方法未知
*/
private
final
int
s
[]={
7
,
12
,
17
,
22
,
7
,
12
,
17
,
22
,
7
,
12
,
17
,
22
,
7
,
12
,
17
,
22
,
5
,
9
,
14
,
20
,
5
,
9
,
14
,
20
,
5
,
9
,
14
,
20
,
5
,
9
,
14
,
20
,
4
,
11
,
16
,
23
,
4
,
11
,
16
,
23
,
4
,
11
,
16
,
23
,
4
,
11
,
16
,
23
,
6
,
10
,
15
,
21
,
6
,
10
,
15
,
21
,
6
,
10
,
15
,
21
,
6
,
10
,
15
,
21
};
/*
*初始化函数
*/
private
void
init
(){
Atemp
=
A
;
Btemp
=
B
;
Ctemp
=
C
;
Dtemp
=
D
;
}
/*
*移动一定位数
*/
private
int
shift
(
int
a
,
int
s
){
return
(
a
<<
s
)|(
a
>>>(
32
-
s
));
//右移的时候,高位一定要补零,而不是补充符号位
}
/*
*主循环
*/
private
void
MainLoop
(
int
M
[]){
int
F
,
g
;
int
a
=
Atemp
;
int
b
=
Btemp
;
int
c
=
Ctemp
;
int
d
=
Dtemp
;
for
(
int
i
=
0
;
i
<
64
;
i
++){
if
(
i
<
16
){
F
=(
b
&
c
)|((~
b
)&
d
);
g
=
i
;
}
else
if
(
i
<
32
){
F
=(
d
&
b
)|((~
d
)&
c
);
g
=(
5
*
i
+
1
)%
16
;
}
else
if
(
i
<
48
){
F
=
b
^
c
^
d
;
g
=(
3
*
i
+
5
)%
16
;
}
else
{
F
=
c
^(
b
|(~
d
));
g
=(
7
*
i
)%
16
;
}
int
tmp
=
d
;
d
=
c
;
c
=
b
;
b
=
b
+
shift
(
a
+
F
+
K
[
i
]+
M
[
g
],
s
[
i
]);
a
=
tmp
;
}
Atemp
=
a
+
Atemp
;
Btemp
=
b
+
Btemp
;
Ctemp
=
c
+
Ctemp
;
Dtemp
=
d
+
Dtemp
;
}
/*
*填充函数
*处理后应满足bits≡448(mod512),字节就是bytes≡56(mode64)
*填充方式为先加一个0,其它位补零
*最后加上64位的原来长度
*/
private
int
[]
add
(
String
str
){
int
num
=((
str
.
length
()+
8
)/
64
)+
1
;
//以512位,64个字节为一组
int
strByte
[]=
new
int
[
num
*
16
];
//64/4=16,所以有16个整数
for
(
int
i
=
0
;
i
<
num
*
16
;
i
++){
//全部初始化0
strByte
[
i
]=
0
;
}
int
i
;
for
(
i
=
0
;
i
<
str
.
length
();
i
++){
strByte
[
i
>>
2
]|=
str
.
charAt
(
i
)<<((
i
%
4
)*
8
);
//一个整数存储四个字节,小端序
}
strByte
[
i
>>
2
]|=
0x80
<<((
i
%
4
)*
8
);
//尾部添加1
/*
*添加原长度,长度指位的长度,所以要乘8,然后是小端序,所以放在倒数第二个,这里长度只用了32位
*/
strByte
[
num
*
16
-
2
]=
str
.
length
()*
8
;
return
strByte
;
}
/*
*调用函数
*/
public
String
getMD5
(
String
source
){
init
();
int
strByte
[]=
add
(
source
);
for
(
int
i
=
0
;
i
<
strByte
.
length
/
16
;
i
++){
int
num
[]=
new
int
[
16
];
for
(
int
j
=
0
;
j
<
16
;
j
++){
num
[
j
]=
strByte
[
i
*
16
+
j
];
}
MainLoop
(
num
);
}
return
changeHex
(
Atemp
)+
changeHex
(
Btemp
)+
changeHex
(
Ctemp
)+
changeHex
(
Dtemp
);
}
/*
*整数变成16进制字符串
*/
private
String
changeHex
(
int
a
){
String
str
=
""
;
for
(
int
i
=
0
;
i
<
4
;
i
++){
str
+=
String
.
format
(
"%2s"
,
Integer
.
toHexString
(((
a
>>
i
*
8
)%(
1
<<
8
))&
0xff
)).
replace
(
' '
,
'0'
);
}
return
str
;
}
/*
*单例
*/
private
static
MD5
instance
;
public
static
MD5
getInstance
(){
if
(
instance
==
null
){
instance
=
new
MD5
();
}
return
instance
;
}
private
MD5
(){};
public
static
void
main
(
String
[]
args
){
String
str
=
MD5
.
getInstance
().
getMD5
(
"你若安好,便是晴天"
);
System
.
out
.
println
(
str
);
}
}
\ No newline at end of file
docs/dataStructures-algorithms/source code/securityAlgorithm/src/main/java/com/snailclimb/ks/securityAlgorithm/MD5Demo.java
已删除
100644 → 0
浏览文件 @
7f506299
package
com.snailclimb.ks.securityAlgorithm
;
import
java.security.MessageDigest
;
public
class
MD5Demo
{
// test
public
static
void
main
(
String
[]
args
)
{
System
.
out
.
println
(
getMD5Code
(
"你若安好,便是晴天"
));
}
private
MD5Demo
()
{
}
// md5加密
public
static
String
getMD5Code
(
String
message
)
{
String
md5Str
=
""
;
try
{
//创建MD5算法消息摘要
MessageDigest
md
=
MessageDigest
.
getInstance
(
"MD5"
);
//生成的哈希值的字节数组
byte
[]
md5Bytes
=
md
.
digest
(
message
.
getBytes
());
md5Str
=
bytes2Hex
(
md5Bytes
);
}
catch
(
Exception
e
)
{
e
.
printStackTrace
();
}
return
md5Str
;
}
// 2进制转16进制
public
static
String
bytes2Hex
(
byte
[]
bytes
)
{
StringBuffer
result
=
new
StringBuffer
();
int
temp
;
try
{
for
(
int
i
=
0
;
i
<
bytes
.
length
;
i
++)
{
temp
=
bytes
[
i
];
if
(
temp
<
0
)
{
temp
+=
256
;
}
if
(
temp
<
16
)
{
result
.
append
(
"0"
);
}
result
.
append
(
Integer
.
toHexString
(
temp
));
}
}
catch
(
Exception
e
)
{
e
.
printStackTrace
();
}
return
result
.
toString
();
}
}
docs/dataStructures-algorithms/source code/securityAlgorithm/src/main/java/com/snailclimb/ks/securityAlgorithm/RSADemo.java
已删除
100644 → 0
浏览文件 @
7f506299
package
com.snailclimb.ks.securityAlgorithm
;
import
org.apache.commons.codec.binary.Base64
;
import
java.security.*
;
import
java.security.spec.PKCS8EncodedKeySpec
;
import
java.security.spec.X509EncodedKeySpec
;
import
java.util.HashMap
;
import
java.util.Map
;
import
javax.crypto.Cipher
;
/**
* Created by humf.需要依赖 commons-codec 包
*/
public
class
RSADemo
{
public
static
void
main
(
String
[]
args
)
throws
Exception
{
Map
<
String
,
Key
>
keyMap
=
initKey
();
String
publicKey
=
getPublicKey
(
keyMap
);
String
privateKey
=
getPrivateKey
(
keyMap
);
System
.
out
.
println
(
keyMap
);
System
.
out
.
println
(
"-----------------------------------"
);
System
.
out
.
println
(
publicKey
);
System
.
out
.
println
(
"-----------------------------------"
);
System
.
out
.
println
(
privateKey
);
System
.
out
.
println
(
"-----------------------------------"
);
byte
[]
encryptByPrivateKey
=
encryptByPrivateKey
(
"123456"
.
getBytes
(),
privateKey
);
byte
[]
encryptByPublicKey
=
encryptByPublicKey
(
"123456"
,
publicKey
);
System
.
out
.
println
(
encryptByPrivateKey
);
System
.
out
.
println
(
"-----------------------------------"
);
System
.
out
.
println
(
encryptByPublicKey
);
System
.
out
.
println
(
"-----------------------------------"
);
String
sign
=
sign
(
encryptByPrivateKey
,
privateKey
);
System
.
out
.
println
(
sign
);
System
.
out
.
println
(
"-----------------------------------"
);
boolean
verify
=
verify
(
encryptByPrivateKey
,
publicKey
,
sign
);
System
.
out
.
println
(
verify
);
System
.
out
.
println
(
"-----------------------------------"
);
byte
[]
decryptByPublicKey
=
decryptByPublicKey
(
encryptByPrivateKey
,
publicKey
);
byte
[]
decryptByPrivateKey
=
decryptByPrivateKey
(
encryptByPublicKey
,
privateKey
);
System
.
out
.
println
(
decryptByPublicKey
);
System
.
out
.
println
(
"-----------------------------------"
);
System
.
out
.
println
(
decryptByPrivateKey
);
}
public
static
final
String
KEY_ALGORITHM
=
"RSA"
;
public
static
final
String
SIGNATURE_ALGORITHM
=
"MD5withRSA"
;
private
static
final
String
PUBLIC_KEY
=
"RSAPublicKey"
;
private
static
final
String
PRIVATE_KEY
=
"RSAPrivateKey"
;
public
static
byte
[]
decryptBASE64
(
String
key
)
{
return
Base64
.
decodeBase64
(
key
);
}
public
static
String
encryptBASE64
(
byte
[]
bytes
)
{
return
Base64
.
encodeBase64String
(
bytes
);
}
/**
* 用私钥对信息生成数字签名
*
* @param data
* 加密数据
* @param privateKey
* 私钥
* @return
* @throws Exception
*/
public
static
String
sign
(
byte
[]
data
,
String
privateKey
)
throws
Exception
{
// 解密由base64编码的私钥
byte
[]
keyBytes
=
decryptBASE64
(
privateKey
);
// 构造PKCS8EncodedKeySpec对象
PKCS8EncodedKeySpec
pkcs8KeySpec
=
new
PKCS8EncodedKeySpec
(
keyBytes
);
// KEY_ALGORITHM 指定的加密算法
KeyFactory
keyFactory
=
KeyFactory
.
getInstance
(
KEY_ALGORITHM
);
// 取私钥匙对象
PrivateKey
priKey
=
keyFactory
.
generatePrivate
(
pkcs8KeySpec
);
// 用私钥对信息生成数字签名
Signature
signature
=
Signature
.
getInstance
(
SIGNATURE_ALGORITHM
);
signature
.
initSign
(
priKey
);
signature
.
update
(
data
);
return
encryptBASE64
(
signature
.
sign
());
}
/**
* 校验数字签名
*
* @param data
* 加密数据
* @param publicKey
* 公钥
* @param sign
* 数字签名
* @return 校验成功返回true 失败返回false
* @throws Exception
*/
public
static
boolean
verify
(
byte
[]
data
,
String
publicKey
,
String
sign
)
throws
Exception
{
// 解密由base64编码的公钥
byte
[]
keyBytes
=
decryptBASE64
(
publicKey
);
// 构造X509EncodedKeySpec对象
X509EncodedKeySpec
keySpec
=
new
X509EncodedKeySpec
(
keyBytes
);
// KEY_ALGORITHM 指定的加密算法
KeyFactory
keyFactory
=
KeyFactory
.
getInstance
(
KEY_ALGORITHM
);
// 取公钥匙对象
PublicKey
pubKey
=
keyFactory
.
generatePublic
(
keySpec
);
Signature
signature
=
Signature
.
getInstance
(
SIGNATURE_ALGORITHM
);
signature
.
initVerify
(
pubKey
);
signature
.
update
(
data
);
// 验证签名是否正常
return
signature
.
verify
(
decryptBASE64
(
sign
));
}
public
static
byte
[]
decryptByPrivateKey
(
byte
[]
data
,
String
key
)
throws
Exception
{
// 对密钥解密
byte
[]
keyBytes
=
decryptBASE64
(
key
);
// 取得私钥
PKCS8EncodedKeySpec
pkcs8KeySpec
=
new
PKCS8EncodedKeySpec
(
keyBytes
);
KeyFactory
keyFactory
=
KeyFactory
.
getInstance
(
KEY_ALGORITHM
);
Key
privateKey
=
keyFactory
.
generatePrivate
(
pkcs8KeySpec
);
// 对数据解密
Cipher
cipher
=
Cipher
.
getInstance
(
keyFactory
.
getAlgorithm
());
cipher
.
init
(
Cipher
.
DECRYPT_MODE
,
privateKey
);
return
cipher
.
doFinal
(
data
);
}
/**
* 解密<br>
* 用私钥解密
*
* @param data
* @param key
* @return
* @throws Exception
*/
public
static
byte
[]
decryptByPrivateKey
(
String
data
,
String
key
)
throws
Exception
{
return
decryptByPrivateKey
(
decryptBASE64
(
data
),
key
);
}
/**
* 解密<br>
* 用公钥解密
*
* @param data
* @param key
* @return
* @throws Exception
*/
public
static
byte
[]
decryptByPublicKey
(
byte
[]
data
,
String
key
)
throws
Exception
{
// 对密钥解密
byte
[]
keyBytes
=
decryptBASE64
(
key
);
// 取得公钥
X509EncodedKeySpec
x509KeySpec
=
new
X509EncodedKeySpec
(
keyBytes
);
KeyFactory
keyFactory
=
KeyFactory
.
getInstance
(
KEY_ALGORITHM
);
Key
publicKey
=
keyFactory
.
generatePublic
(
x509KeySpec
);
// 对数据解密
Cipher
cipher
=
Cipher
.
getInstance
(
keyFactory
.
getAlgorithm
());
cipher
.
init
(
Cipher
.
DECRYPT_MODE
,
publicKey
);
return
cipher
.
doFinal
(
data
);
}
/**
* 加密<br>
* 用公钥加密
*
* @param data
* @param key
* @return
* @throws Exception
*/
public
static
byte
[]
encryptByPublicKey
(
String
data
,
String
key
)
throws
Exception
{
// 对公钥解密
byte
[]
keyBytes
=
decryptBASE64
(
key
);
// 取得公钥
X509EncodedKeySpec
x509KeySpec
=
new
X509EncodedKeySpec
(
keyBytes
);
KeyFactory
keyFactory
=
KeyFactory
.
getInstance
(
KEY_ALGORITHM
);
Key
publicKey
=
keyFactory
.
generatePublic
(
x509KeySpec
);
// 对数据加密
Cipher
cipher
=
Cipher
.
getInstance
(
keyFactory
.
getAlgorithm
());
cipher
.
init
(
Cipher
.
ENCRYPT_MODE
,
publicKey
);
return
cipher
.
doFinal
(
data
.
getBytes
());
}
/**
* 加密<br>
* 用私钥加密
*
* @param data
* @param key
* @return
* @throws Exception
*/
public
static
byte
[]
encryptByPrivateKey
(
byte
[]
data
,
String
key
)
throws
Exception
{
// 对密钥解密
byte
[]
keyBytes
=
decryptBASE64
(
key
);
// 取得私钥
PKCS8EncodedKeySpec
pkcs8KeySpec
=
new
PKCS8EncodedKeySpec
(
keyBytes
);
KeyFactory
keyFactory
=
KeyFactory
.
getInstance
(
KEY_ALGORITHM
);
Key
privateKey
=
keyFactory
.
generatePrivate
(
pkcs8KeySpec
);
// 对数据加密
Cipher
cipher
=
Cipher
.
getInstance
(
keyFactory
.
getAlgorithm
());
cipher
.
init
(
Cipher
.
ENCRYPT_MODE
,
privateKey
);
return
cipher
.
doFinal
(
data
);
}
/**
* 取得私钥
*
* @param keyMap
* @return
* @throws Exception
*/
public
static
String
getPrivateKey
(
Map
<
String
,
Key
>
keyMap
)
throws
Exception
{
Key
key
=
(
Key
)
keyMap
.
get
(
PRIVATE_KEY
);
return
encryptBASE64
(
key
.
getEncoded
());
}
/**
* 取得公钥
*
* @param keyMap
* @return
* @throws Exception
*/
public
static
String
getPublicKey
(
Map
<
String
,
Key
>
keyMap
)
throws
Exception
{
Key
key
=
keyMap
.
get
(
PUBLIC_KEY
);
return
encryptBASE64
(
key
.
getEncoded
());
}
/**
* 初始化密钥
*
* @return
* @throws Exception
*/
public
static
Map
<
String
,
Key
>
initKey
()
throws
Exception
{
KeyPairGenerator
keyPairGen
=
KeyPairGenerator
.
getInstance
(
KEY_ALGORITHM
);
keyPairGen
.
initialize
(
1024
);
KeyPair
keyPair
=
keyPairGen
.
generateKeyPair
();
Map
<
String
,
Key
>
keyMap
=
new
HashMap
(
2
);
keyMap
.
put
(
PUBLIC_KEY
,
keyPair
.
getPublic
());
// 公钥
keyMap
.
put
(
PRIVATE_KEY
,
keyPair
.
getPrivate
());
// 私钥
return
keyMap
;
}
}
\ No newline at end of file
docs/dataStructures-algorithms/source code/securityAlgorithm/src/main/java/com/snailclimb/ks/securityAlgorithm/SHA1Demo.java
已删除
100644 → 0
浏览文件 @
7f506299
package
com.snailclimb.ks.securityAlgorithm
;
import
java.io.UnsupportedEncodingException
;
import
java.security.MessageDigest
;
import
java.security.NoSuchAlgorithmException
;
public
class
SHA1Demo
{
public
static
void
main
(
String
[]
args
)
{
// TODO Auto-generated method stub
System
.
out
.
println
(
getSha1
(
"你若安好,便是晴天"
));
}
public
static
String
getSha1
(
String
str
)
{
if
(
null
==
str
||
0
==
str
.
length
())
{
return
null
;
}
char
[]
hexDigits
=
{
'0'
,
'1'
,
'2'
,
'3'
,
'4'
,
'5'
,
'6'
,
'7'
,
'8'
,
'9'
,
'a'
,
'b'
,
'c'
,
'd'
,
'e'
,
'f'
};
try
{
//创建SHA1算法消息摘要对象
MessageDigest
mdTemp
=
MessageDigest
.
getInstance
(
"SHA1"
);
//使用指定的字节数组更新摘要。
mdTemp
.
update
(
str
.
getBytes
(
"UTF-8"
));
//生成的哈希值的字节数组
byte
[]
md
=
mdTemp
.
digest
();
//SHA1算法生成信息摘要关键过程
int
j
=
md
.
length
;
char
[]
buf
=
new
char
[
j
*
2
];
int
k
=
0
;
for
(
int
i
=
0
;
i
<
j
;
i
++)
{
byte
byte0
=
md
[
i
];
buf
[
k
++]
=
hexDigits
[
byte0
>>>
4
&
0xf
];
buf
[
k
++]
=
hexDigits
[
byte0
&
0xf
];
}
return
new
String
(
buf
);
}
catch
(
NoSuchAlgorithmException
e
)
{
e
.
printStackTrace
();
}
catch
(
UnsupportedEncodingException
e
)
{
e
.
printStackTrace
();
}
return
"0"
;
}
}
docs/dataStructures-algorithms/source code/securityAlgorithm/src/main/java/com/snailclimb/ks/securityAlgorithm/readme
已删除
100644 → 0
浏览文件 @
7f506299
Des算法参考:http://blog.csdn.net/super_cui/article/details/70820983
IDEA算法参考:https://www.xttblog.com/?p=1121
RSA算法实现参考:https://www.cnblogs.com/xlhan/p/7120488.html
\ No newline at end of file
docs/dataStructures-algorithms/source code/securityAlgorithm/src/test/java/com/snailclimb/ks/securityAlgorithm/AppTest.java
已删除
100644 → 0
浏览文件 @
7f506299
package
com.snailclimb.ks.securityAlgorithm
;
import
junit.framework.Test
;
import
junit.framework.TestCase
;
import
junit.framework.TestSuite
;
/**
* Unit test for simple App.
*/
public
class
AppTest
extends
TestCase
{
/**
* Create the test case
*
* @param testName name of the test case
*/
public
AppTest
(
String
testName
)
{
super
(
testName
);
}
/**
* @return the suite of tests being tested
*/
public
static
Test
suite
()
{
return
new
TestSuite
(
AppTest
.
class
);
}
/**
* Rigourous Test :-)
*/
public
void
testApp
()
{
assertTrue
(
true
);
}
}
docs/dataStructures-algorithms/
算法题解析/公司真题/网易2018校招编程题1-3
.md
→
docs/dataStructures-algorithms/
公司真题
.md
浏览文件 @
63cca039
# 网易 2018
下面三道编程题来自网易2018校招编程题,这三道应该来说是非常简单的编程题了,这些题目大家稍微有点编程和数学基础的话应该没什么问题。看答案之前一定要自己先想一下如果是自己做的话会怎么去做,然后再对照这我的答案看看,和你自己想的有什么区别?那一种方法更好?
![
问题
](
https://user-gold-cdn.xitu.io/2018/7/7/1647557d5a1474d7?w=1024&h=1024&f=jpeg&s=638271
)
> # 问题
## 问题
## 一 获得特定数量硬币问题
##
#
一 获得特定数量硬币问题
小易准备去魔法王国采购魔法神器,购买魔法神器需要使用魔法币,但是小易现在一枚魔法币都没有,但是小易有两台魔法机器可以通过投入x(x可以为0)个魔法币产生更多的魔法币。
...
...
@@ -15,33 +16,30 @@
**输入描述:**
输入包括一行,包括一个正整数n(1 ≤ n ≤ 10^9),表示小易需要的魔法币数量。
**输出描述:**
输出一个字符串,每个字符表示该次小易选取投入的魔法机器。其中只包含字符'1'和'2'。
**输入例子1:**
10
**输出例子1:**
122
## 二 求“相反数”问题
##
#
二 求“相反数”问题
为了得到一个数的"相反数",我们将这个数的数字顺序颠倒,然后再加上原先的数得到"相反数"。例如,为了得到1325的"相反数",首先我们将该数的数字顺序颠倒,我们得到5231,之后再加上原先的数,我们得到5231+1325=6556.如果颠倒之后的数字有前缀零,前缀零将会被忽略。例如n = 100, 颠倒之后是1.
**输入描述:**
输入包括一个整数n,(1 ≤ n ≤ 10^5)
**输出描述:**
输出一个整数,表示n的相反数
**输入例子1:**
1325
**输出例子1:**
6556
## 三 字符串碎片的平均长度
##
#
三 字符串碎片的平均长度
一个由小写字母组成的字符串可以看成一些同一字母的最大碎片组成的。例如,"aaabbaaac"是由下面碎片组成的:'aaa','bb','c'。牛牛现在给定一个字符串,请你帮助计算这个字符串的所有碎片的平均长度是多少。
**输入描述:**
输入包括一个字符串s,字符串s的长度length(1 ≤ length ≤ 50),s只含小写字母('a'-'z')
**输出描述:**
输出一个整数,表示所有碎片的平均长度,四舍五入保留两位小数。
**如样例所示:**
s = "aaabbaaac"
...
...
@@ -51,19 +49,18 @@
**输出例子1:**
2.25
![
答案
](
https://user-gold-cdn.xitu.io/2018/7/7/16475582faddc9b2?w=1024&h=1024&f=jpeg&s=531663
)
> # 答案
## 答案
## 一 获得特定数量硬币问题
##
#
一 获得特定数量硬币问题
### 分析:
###
#
分析:
作为该试卷的第一题,这道题应该只要思路正确就很简单了。
解题关键:明确魔法机器1只能产生奇数,魔法机器2只能产生偶数即可。我们从后往前一步一步推回去即可。
### 示例代码
#### 示例代码
注意:由于用户的输入不确定性,一般是为了程序高可用性使需要将捕获用户输入异常然后友好提示用户输入类型错误并重新输入的。所以下面我给了两个版本,这两个版本都是正确的。这里只是给大家演示如何捕获输入类型异常,后面的题目中我给的代码没有异常处理的部分,参照下面两个示例代码,应该很容易添加。(PS:企业面试中没有明确就不用添加异常处理,当然你有的话也更好)
**不带输入异常处理判断的版本:**
...
...
@@ -141,32 +138,33 @@ public class Main {
```
### 二 求“相反数”问题
## 二 求“相反数”问题
### 分析:
#### 分析:
解决本道题有几种不同的方法,但是最快速的方法就是利用reverse()方法反转字符串然后再将字符串转换成int类型的整数,这个方法是快速解决本题关键。我们先来回顾一下下面两个知识点:
**1)String转int;**
在 Java 中要将 String 类型转化为 int 类型时,需要使用 Integer 类中的 parseInt() 方法或者 valueOf() 方法进行转换.
```
java
String
str
=
"123"
;
int
a
=
Integer
.
parseInt
(
str
);
```
或
```
java
String
str
=
"123"
;
int
a
=
Integer
.
valueOf
(
str
).
intValue
()
;
```
**2)next()和nextLine()的区别**
在Java中输入字符串有两种方法,就是next()和nextLine().两者的区别就是:nextLine()的输入是碰到回车就终止输入,而next()方法是碰到空格,回车,Tab键都会被视为终止符。所以next()不会得到带空格的字符串,而nextLine()可以得到带空格的字符串。
### 示例代码:
###
#
示例代码:
```
java
import
java.util.Scanner
;
...
...
@@ -192,15 +190,15 @@ public class Main {
}
```
## 三 字符串碎片的平均长度
##
#
三 字符串碎片的平均长度
### 分析:
###
#
分析:
这道题的意思也就是要求:(字符串的总长度)/(相同字母团构成的字符串的个数)。
这样就很简单了,就变成了字符串的字符之间的比较。如果需要比较字符串的字符的话,我们可以利用charAt(i)方法:取出特定位置的字符与后一个字符比较,或者利用toCharArray()方法将字符串转换成字符数组采用同样的方法做比较。
### 示例代码
###
#
示例代码
**利用charAt(i)方法:**
...
...
docs/dataStructures-algorithms/
搞定BAT面试——
几道常见的子符串算法题.md
→
docs/dataStructures-algorithms/几道常见的子符串算法题.md
浏览文件 @
63cca039
文件已移动
docs/dataStructures-algorithms/
Leetcode-LinkList1
.md
→
docs/dataStructures-algorithms/
几道常见的链表算法题
.md
浏览文件 @
63cca039
文件已移动
docs/dataStructures-algorithms/剑指offer部分编程题.md
0 → 100644
浏览文件 @
63cca039
此差异已折叠。
点击以展开。
docs/dataStructures-algorithms/常见安全算法(MD5、SHA1、Base64等等)总结.md
已删除
100644 → 0
浏览文件 @
7f506299
此差异已折叠。
点击以展开。
docs/dataStructures-algorithms/算法.md
已删除
100644 → 0
浏览文件 @
7f506299
## LeetCode
[
LeetCode(中国)官网
](
https://leetcode-cn.com/
)
[
如何高效地使用 LeetCode
](
https://leetcode-cn.com/articles/%E5%A6%82%E4%BD%95%E9%AB%98%E6%95%88%E5%9C%B0%E4%BD%BF%E7%94%A8-leetcode/
)
## 牛客网:
[
牛客网首页
](
https://www.nowcoder.com
)
> ### **[剑指offer编程题](https://www.nowcoder.com/ta/coding-interviews)**
**分类解析:**
-
[
(1)斐波那契数列问题和跳台阶问题
](
https://github.com/Snailclimb/Java-Guide/tree/master/数据结构与算法/算法题解析/剑指offer/(1)斐波那契数列问题和跳台阶问题.md
)
-
[
(2)二维数组查找和替换空格问题
](
https://github.com/Snailclimb/Java-Guide/tree/master/数据结构与算法/算法题解析/剑指offer/(2)二维数组查找和替换空格问题.md
)
-
[
(3)数值的整数次方和调整数组元素顺序
](
https://github.com/Snailclimb/Java-Guide/tree/master/数据结构与算法/算法题解析/剑指offer/(3)数值的整数次方和调整数组元素顺序.md
)
-
[
(4)链表相关编程题
](
https://github.com/Snailclimb/Java-Guide/tree/master/数据结构与算法/算法题解析/剑指offer/(4)链表相关编程题.md
)
-
[
(5)栈变队列和栈的压入、弹出序列
](
https://github.com/Snailclimb/Java-Guide/tree/master/数据结构与算法/算法题解析/剑指offer/(5)栈变队列和栈的压入、弹出序列.md
)
> ### [2017校招真题](https://www.nowcoder.com/ta/2017test)
> ### [华为机试题](https://www.nowcoder.com/ta/huawei)
## 公司真题
> [ 网易2018校园招聘编程题真题集合](https://www.nowcoder.com/test/6910869/summary)
**解析:**
-
[
网易2018校招编程题1-3
](
https://github.com/Snailclimb/Java-Guide/tree/master/数据结构与算法/算法题解析/公司真题/网易2018校招编程题1-3.md
)
> [ 网易2018校招内推编程题集合](https://www.nowcoder.com/test/6291726/summary)
> [2017年校招全国统一模拟笔试(第五场)编程题集合](https://www.nowcoder.com/test/5986669/summary)
> [2017年校招全国统一模拟笔试(第四场)编程题集合](https://www.nowcoder.com/test/5507925/summary)
> [2017年校招全国统一模拟笔试(第三场)编程题集合](https://www.nowcoder.com/test/5217106/summary)
> [2017年校招全国统一模拟笔试(第二场)编程题集合](https://www.nowcoder.com/test/4546329/summary)
> [ 2017年校招全国统一模拟笔试(第一场)编程题集合](https://www.nowcoder.com/test/4236887/summary)
> [百度2017春招笔试真题编程题集合](https://www.nowcoder.com/test/4998655/summary)
> [网易2017春招笔试真题编程题集合](https://www.nowcoder.com/test/4575457/summary)
> [网易2017秋招编程题集合](https://www.nowcoder.com/test/2811407/summary)
> [网易有道2017内推编程题](https://www.nowcoder.com/test/2385858/summary)
> [ 滴滴出行2017秋招笔试真题-编程题汇总](https://www.nowcoder.com/test/3701760/summary)
> [腾讯2017暑期实习生编程题](https://www.nowcoder.com/test/1725829/summary)
> [今日头条2017客户端工程师实习生笔试题](https://www.nowcoder.com/test/1649301/summary)
> [今日头条2017后端工程师实习生笔试题](https://www.nowcoder.com/test/1649268/summary)
## 排序算法:
[
图解排序算法(一)之3种简单排序(选择,冒泡,直接插入)
](
http://www.cnblogs.com/chengxiao/p/6103002.html
)
[
图解排序算法(二)之希尔排序
](
https://www.cnblogs.com/chengxiao/p/6104371.html
)
[
图解排序算法(三)之堆排序
](
http://www.cnblogs.com/chengxiao/p/6129630.html
)
[
图解排序算法(四)之归并排序
](
http://www.cnblogs.com/chengxiao/p/6194356.html
)
[
图解排序算法(五)之快速排序——三数取中法
](
http://www.cnblogs.com/chengxiao/p/6262208.html
)
docs/dataStructures-algorithms/算法学习资源推荐.md
0 → 100644
浏览文件 @
63cca039
我比较推荐大家可以刷一下 Leetcode ,我自己平时没事也会刷一下,我觉得刷 Leetcode 不仅是为了能让你更从容地面对面试中的手撕算法问题,更可以提高你的编程思维能力、解决问题的能力以及你对某门编程语言 API 的熟练度。当然牛客网也有一些算法题,我下面也整理了一些。
## LeetCode
-
[
LeetCode(中国)官网
](
https://leetcode-cn.com/
)
-
[
如何高效地使用 LeetCode
](
https://leetcode-cn.com/articles/%E5%A6%82%E4%BD%95%E9%AB%98%E6%95%88%E5%9C%B0%E4%BD%BF%E7%94%A8-leetcode/
)
## 牛客网:
-
[
牛客网官网
](
https://www.nowcoder.com
)
-
[
剑指offer编程题
](
https://www.nowcoder.com/ta/coding-interviews
)
-
[
2017校招真题
](
https://www.nowcoder.com/ta/2017test
)
-
[
华为机试题
](
https://www.nowcoder.com/ta/huawei
)
## 公司真题
-
[
网易2018校园招聘编程题真题集合
](
https://www.nowcoder.com/test/6910869/summary
)
-
[
网易2018校招内推编程题集合
](
https://www.nowcoder.com/test/6291726/summary
)
-
[
2017年校招全国统一模拟笔试(第五场)编程题集合
](
https://www.nowcoder.com/test/5986669/summary
)
-
[
2017年校招全国统一模拟笔试(第四场)编程题集合
](
https://www.nowcoder.com/test/5507925/summary
)
-
[
2017年校招全国统一模拟笔试(第三场)编程题集合
](
https://www.nowcoder.com/test/5217106/summary
)
-
[
2017年校招全国统一模拟笔试(第二场)编程题集合
](
https://www.nowcoder.com/test/4546329/summary
)
-
[
2017年校招全国统一模拟笔试(第一场)编程题集合
](
https://www.nowcoder.com/test/4236887/summary
)
-
[
百度2017春招笔试真题编程题集合
](
https://www.nowcoder.com/test/4998655/summary
)
-
[
网易2017春招笔试真题编程题集合
](
https://www.nowcoder.com/test/4575457/summary
)
-
[
网易2017秋招编程题集合
](
https://www.nowcoder.com/test/2811407/summary
)
-
[
网易有道2017内推编程题
](
https://www.nowcoder.com/test/2385858/summary
)
-
[
滴滴出行2017秋招笔试真题-编程题汇总
](
https://www.nowcoder.com/test/3701760/summary
)
-
[
腾讯2017暑期实习生编程题
](
https://www.nowcoder.com/test/1725829/summary
)
-
[
今日头条2017客户端工程师实习生笔试题
](
https://www.nowcoder.com/test/1649301/summary
)
-
[
今日头条2017后端工程师实习生笔试题
](
https://www.nowcoder.com/test/1649268/summary
)
docs/dataStructures-algorithms/算法题解析/剑指offer/(1)斐波那契数列问题和跳台阶问题.md
已删除
100644 → 0
浏览文件 @
7f506299
### 一 斐波那契数列
#### **题目描述:**
大家都知道斐波那契数列,现在要求输入一个整数n,请你输出斐波那契数列的第n项。
n<=39
#### **问题分析:**
可以肯定的是这一题通过递归的方式是肯定能做出来,但是这样会有一个很大的问题,那就是递归大量的重复计算会导致内存溢出。另外可以使用迭代法,用fn1和fn2保存计算过程中的结果,并复用起来。下面我会把两个方法示例代码都给出来并给出两个方法的运行时间对比。
#### **示例代码:**
**采用迭代法:**
```
java
int
Fibonacci
(
int
number
)
{
if
(
number
<=
0
)
{
return
0
;
}
if
(
number
==
1
||
number
==
2
)
{
return
1
;
}
int
first
=
1
,
second
=
1
,
third
=
0
;
for
(
int
i
=
3
;
i
<=
number
;
i
++)
{
third
=
first
+
second
;
first
=
second
;
second
=
third
;
}
return
third
;
}
```
**采用递归:**
```
java
public
int
Fibonacci
(
int
n
)
{
if
(
n
<=
0
)
{
return
0
;
}
if
(
n
==
1
||
n
==
2
)
{
return
1
;
}
return
Fibonacci
(
n
-
2
)
+
Fibonacci
(
n
-
1
);
}
```
#### **运行时间对比:**
假设n为40我们分别使用迭代法和递归法计算,计算结果如下:
1.
迭代法
![
迭代法
](
https://ws1.sinaimg.cn/large/006rNwoDgy1fpydt5as85j308a025dfl.jpg
)
2.
递归法
!
[
递归法
](
https://ws1.sinaimg.cn/large/006rNwoDgy1fpydt2d1k3j30ed02kt8i.jpg
)
### 二 跳台阶问题
#### **题目描述:**
一只青蛙一次可以跳上1级台阶,也可以跳上2级。求该青蛙跳上一个n级的台阶总共有多少种跳法。
#### **问题分析:**
**正常分析法:**
a.如果两种跳法,1阶或者2阶,那么假定第一次跳的是一阶,那么剩下的是n-1个台阶,跳法是f(n-1);
b.假定第一次跳的是2阶,那么剩下的是n-2个台阶,跳法是f(n-2)
c.由a,b假设可以得出总跳法为: f(n) = f(n-1) + f(n-2)
d.然后通过实际的情况可以得出:只有一阶的时候 f(1) = 1 ,只有两阶的时候可以有 f(2) = 2
**找规律分析法:**
f(1) = 1, f(2) = 2, f(3) = 3, f(4) = 5, 可以总结出f(n) = f(n-1) + f(n-2)的规律。
但是为什么会出现这样的规律呢?假设现在6个台阶,我们可以从第5跳一步到6,这样的话有多少种方案跳到5就有多少种方案跳到6,另外我们也可以从4跳两步跳到6,跳到4有多少种方案的话,就有多少种方案跳到6,其他的不能从3跳到6什么的啦,所以最后就是f(6) = f(5) + f(4);这样子也很好理解变态跳台阶的问题了。
**所以这道题其实就是斐波那契数列的问题。**
代码只需要在上一题的代码稍做修改即可。和上一题唯一不同的就是这一题的初始元素变为 1 2 3 5 8.....而上一题为1 1 2 3 5 .......。另外这一题也可以用递归做,但是递归效率太低,所以我这里只给出了迭代方式的代码。
#### **示例代码:**
```
java
int
jumpFloor
(
int
number
)
{
if
(
number
<=
0
)
{
return
0
;
}
if
(
number
==
1
)
{
return
1
;
}
if
(
number
==
2
)
{
return
2
;
}
int
first
=
1
,
second
=
2
,
third
=
0
;
for
(
int
i
=
3
;
i
<=
number
;
i
++)
{
third
=
first
+
second
;
first
=
second
;
second
=
third
;
}
return
third
;
}
```
### 三 变态跳台阶问题
#### **题目描述:**
一只青蛙一次可以跳上1级台阶,也可以跳上2级……它也可以跳上n级。求该青蛙跳上一个n级的台阶总共有多少种跳法。
#### **问题分析:**
假设n>=2,第一步有n种跳法:跳1级、跳2级、到跳n级
跳1级,剩下n-1级,则剩下跳法是f(n-1)
跳2级,剩下n-2级,则剩下跳法是f(n-2)
......
跳n-1级,剩下1级,则剩下跳法是f(1)
跳n级,剩下0级,则剩下跳法是f(0)
所以在n>=2的情况下:
f(n)=f(n-1)+f(n-2)+...+f(1)
因为f(n-1)=f(n-2)+f(n-3)+...+f(1)
所以f(n)=2
*f(n-1) 又f(1)=1,所以可得**f(n)=2^(number-1)*
*
#### **示例代码:**
```
java
int
JumpFloorII
(
int
number
)
{
return
1
<<
--
number
;
//2^(number-1)用位移操作进行,更快
}
```
#### **补充:**
**java中有三种移位运算符:**
1.
“<<” :
**左移运算符**
,等同于乘2的n次方
2.
“>>”:
**右移运算符**
,等同于除2的n次方
3.
“>>>”
**无符号右移运算符**
,不管移动前最高位是0还是1,右移后左侧产生的空位部分都以0来填充。与>>类似。
例:
int a = 16;
int b = a << 2;//左移2,等同于16
* 2的2次方,也就是16 *
4
int c = a >> 2;//右移2,等同于16 / 2的2次方,也就是16 / 4
docs/dataStructures-algorithms/算法题解析/剑指offer/(2)二维数组查找和替换空格问题.md
已删除
100644 → 0
浏览文件 @
7f506299
### 一 二维数组查找
#### **题目描述:**
在一个二维数组中,每一行都按照从左到右递增的顺序排序,每一列都按照从上到下递增的顺序排序。请完成一个函数,输入这样的一个二维数组和一个整数,判断数组中是否含有该整数。
#### **问题解析:**
这一道题还是比较简单的,我们需要考虑的是如何做,效率最快。这里有一种很好理解的思路:
> 矩阵是有序的,从左下角来看,向上数字递减,向右数字递增,
因此从左下角开始查找,当要查找数字比左下角数字大时。右移
要查找数字比左下角数字小时,上移。这样找的速度最快。
#### **示例代码:**
```
java
public
boolean
Find
(
int
target
,
int
[][]
array
)
{
//基本思路从左下角开始找,这样速度最快
int
row
=
array
.
length
-
1
;
//行
int
column
=
0
;
//列
//当行数大于0,当前列数小于总列数时循环条件成立
while
((
row
>=
0
)&&
(
column
<
array
[
0
].
length
)){
if
(
array
[
row
][
column
]
>
target
){
row
--;
}
else
if
(
array
[
row
][
column
]
<
target
){
column
++;
}
else
{
return
true
;
}
}
return
false
;
}
```
### 二 替换空格
#### **题目描述:**
请实现一个函数,将一个字符串中的空格替换成“%20”。例如,当字符串为We Are Happy.则经过替换之后的字符串为We%20Are%20Happy。
#### **问题分析:**
这道题不难,我们可以通过循环判断字符串的字符是否为空格,是的话就利用append()方法添加追加“%20”,否则还是追加原字符。
或者最简单的方法就是利用: replaceAll(String regex,String replacement)方法了,一行代码就可以解决。
#### **示例代码:**
**常规做法:**
```
java
public
String
replaceSpace
(
StringBuffer
str
)
{
StringBuffer
out
=
new
StringBuffer
();
for
(
int
i
=
0
;
i
<
str
.
toString
().
length
();
i
++)
{
char
b
=
str
.
charAt
(
i
);
if
(
String
.
valueOf
(
b
).
equals
(
" "
)){
out
.
append
(
"%20"
);
}
else
{
out
.
append
(
b
);
}
}
return
out
.
toString
();
}
```
**一行代码解决:**
```
java
public
String
replaceSpace
(
StringBuffer
str
)
{
//return str.toString().replaceAll(" ", "%20");
//public String replaceAll(String regex,String replacement)
//用给定的替换替换与给定的regular expression匹配的此字符串的每个子字符串。
//\ 转义字符. 如果你要使用 "\" 本身, 则应该使用 "\\". String类型中的空格用“\s”表示,所以我这里猜测"\\s"就是代表空格的意思
return
str
.
toString
().
replaceAll
(
"\\s"
,
"%20"
);
}
```
docs/dataStructures-algorithms/算法题解析/剑指offer/(3)数值的整数次方和调整数组元素顺序.md
已删除
100644 → 0
浏览文件 @
7f506299
### 一 数值的整数次方
#### **题目描述:**
给定一个double类型的浮点数base和int类型的整数exponent。求base的exponent次方。
#### **问题解析:**
这道题算是比较麻烦和难一点的一个了。我这里采用的是
**二分幂**
思想,当然也可以采用
**快速幂**
。
更具剑指offer书中细节,该题的解题思路如下:
1.
当底数为0且指数<0时,会出现对0求倒数的情况,需进行错误处理,设置一个全局变量;
2.
判断底数是否等于0,由于base为double型,所以不能直接用==判断
3.
优化求幂函数(二分幂)。
当n为偶数,a^n =(a^n/2)
*
(a^n/2);
当n为奇数,a^n = a^[(n-1)/2]
* a^[(n-1)/2] *
a。时间复杂度O(logn)
**时间复杂度**
:O(logn)
#### **示例代码:**
```
java
public
class
Solution
{
boolean
invalidInput
=
false
;
public
double
Power
(
double
base
,
int
exponent
)
{
//如果底数等于0并且指数小于0
//由于base为double型,不能直接用==判断
if
(
equal
(
base
,
0.0
)&&
exponent
<
0
){
invalidInput
=
true
;
return
0.0
;
}
int
absexponent
=
exponent
;
//如果指数小于0,将指数转正
if
(
exponent
<
0
)
absexponent
=-
exponent
;
//getPower方法求出base的exponent次方。
double
res
=
getPower
(
base
,
absexponent
);
//如果指数小于0,所得结果为上面求的结果的倒数
if
(
exponent
<
0
)
res
=
1.0
/
res
;
return
res
;
}
//比较两个double型变量是否相等的方法
boolean
equal
(
double
num1
,
double
num2
){
if
(
num1
-
num2
>-
0.000001
&&
num1
-
num2
<
0.000001
)
return
true
;
else
return
false
;
}
//求出b的e次方的方法
double
getPower
(
double
b
,
int
e
){
//如果指数为0,返回1
if
(
e
==
0
)
return
1.0
;
//如果指数为1,返回b
if
(
e
==
1
)
return
b
;
//e>>1相等于e/2,这里就是求a^n =(a^n/2)*(a^n/2)
double
result
=
getPower
(
b
,
e
>>
1
);
result
*=
result
;
//如果指数n为奇数,则要再乘一次底数base
if
((
e
&
1
)==
1
)
result
*=
b
;
return
result
;
}
}
```
当然这一题也可以采用笨方法:累乘。不过这种方法的时间复杂度为O(n),这样没有前一种方法效率高。
```
java
// 使用累乘
public
double
powerAnother
(
double
base
,
int
exponent
)
{
double
result
=
1.0
;
for
(
int
i
=
0
;
i
<
Math
.
abs
(
exponent
);
i
++)
{
result
*=
base
;
}
if
(
exponent
>=
0
)
return
result
;
else
return
1
/
result
;
}
```
### 二 调整数组顺序使奇数位于偶数前面
#### **题目描述:**
输入一个整数数组,实现一个函数来调整该数组中数字的顺序,使得所有的奇数位于数组的前半部分,所有的偶数位于位于数组的后半部分,并保证奇数和奇数,偶数和偶数之间的相对位置不变。
#### **问题解析:**
这道题有挺多种解法的,给大家介绍一种我觉得挺好理解的方法:
我们首先统计奇数的个数假设为n,然后新建一个等长数组,然后通过循环判断原数组中的元素为偶数还是奇数。如果是则从数组下标0的元素开始,把该奇数添加到新数组;如果是偶数则从数组下标为n的元素开始把该偶数添加到新数组中。
#### **示例代码:**
时间复杂度为O(n),空间复杂度为O(n)的算法
```
java
public
class
Solution
{
public
void
reOrderArray
(
int
[]
array
)
{
//如果数组长度等于0或者等于1,什么都不做直接返回
if
(
array
.
length
==
0
||
array
.
length
==
1
)
return
;
//oddCount:保存奇数个数
//oddBegin:奇数从数组头部开始添加
int
oddCount
=
0
,
oddBegin
=
0
;
//新建一个数组
int
[]
newArray
=
new
int
[
array
.
length
];
//计算出(数组中的奇数个数)开始添加元素
for
(
int
i
=
0
;
i
<
array
.
length
;
i
++){
if
((
array
[
i
]&
1
)==
1
)
oddCount
++;
}
for
(
int
i
=
0
;
i
<
array
.
length
;
i
++){
//如果数为基数新数组从头开始添加元素
//如果为偶数就从oddCount(数组中的奇数个数)开始添加元素
if
((
array
[
i
]&
1
)==
1
)
newArray
[
oddBegin
++]=
array
[
i
];
else
newArray
[
oddCount
++]=
array
[
i
];
}
for
(
int
i
=
0
;
i
<
array
.
length
;
i
++){
array
[
i
]=
newArray
[
i
];
}
}
}
```
docs/dataStructures-algorithms/算法题解析/剑指offer/(4)链表相关编程题.md
已删除
100644 → 0
浏览文件 @
7f506299
### 一 链表中倒数第k个节点
#### **题目描述:**
输入一个链表,输出该链表中倒数第k个结点
#### **问题分析:**
**一句话概括:**
两个指针一个指针p1先开始跑,指针p1跑到k-1个节点后,另一个节点p2开始跑,当p1跑到最后时,p2所指的指针就是倒数第k个节点。
**思想的简单理解:**
前提假设:链表的结点个数(长度)为n。
规律一:要找到倒数第k个结点,需要向前走多少步呢?比如倒数第一个结点,需要走n步,那倒数第二个结点呢?很明显是向前走了n-1步,所以可以找到规律是找到倒数第k个结点,需要向前走n-k+1步。
**算法开始:**
1.
设两个都指向head的指针p1和p2,当p1走了k-1步的时候,停下来。p2之前一直不动。
2.
p1的下一步是走第k步,这个时候,p2开始一起动了。至于为什么p2这个时候动呢?看下面的分析。
3.
当p1走到链表的尾部时,即p1走了n步。由于我们知道p2是在p1走了k-1步才开始动的,也就是说p1和p2永远差k-1步。所以当p1走了n步时,p2走的应该是在n-(k-1)步。即p2走了n-k+1步,此时巧妙的是p2正好指向的是规律一的倒数第k个结点处。
这样是不是很好理解了呢?
#### **考察内容:**
链表+代码的鲁棒性
#### **示例代码:**
```
java
/*
//链表类
public class ListNode {
int val;
ListNode next = null;
ListNode(int val) {
this.val = val;
}
}*/
//时间复杂度O(n),一次遍历即可
public
class
Solution
{
public
ListNode
FindKthToTail
(
ListNode
head
,
int
k
)
{
ListNode
pre
=
null
,
p
=
null
;
//两个指针都指向头结点
p
=
head
;
pre
=
head
;
//记录k值
int
a
=
k
;
//记录节点的个数
int
count
=
0
;
//p指针先跑,并且记录节点数,当p指针跑了k-1个节点后,pre指针开始跑,
//当p指针跑到最后时,pre所指指针就是倒数第k个节点
while
(
p
!=
null
){
p
=
p
.
next
;
count
++;
if
(
k
<
1
){
pre
=
pre
.
next
;
}
k
--;
}
//如果节点个数小于所求的倒数第k个节点,则返回空
if
(
count
<
a
)
return
null
;
return
pre
;
}
}
```
### 二 反转链表
#### **题目描述:**
输入一个链表,反转链表后,输出链表的所有元素。
#### **问题分析:**
链表的很常规的一道题,这一道题思路不算难,但自己实现起来真的可能会感觉无从下手,我是参考了别人的代码。
思路就是我们根据链表的特点,前一个节点指向下一个节点的特点,把后面的节点移到前面来。
就比如下图:我们把1节点和2节点互换位置,然后再将3节点指向2节点,4节点指向3节点,这样以来下面的链表就被反转了。
![
链表
](
https://img-blog.csdn.net/20160420134000174
)
#### **考察内容:**
链表+代码的鲁棒性
#### **示例代码:**
```
java
/*
public class ListNode {
int val;
ListNode next = null;
ListNode(int val) {
this.val = val;
}
}*/
public
class
Solution
{
public
ListNode
ReverseList
(
ListNode
head
)
{
ListNode
next
=
null
;
ListNode
pre
=
null
;
while
(
head
!=
null
)
{
//保存要反转到头来的那个节点
next
=
head
.
next
;
//要反转的那个节点指向已经反转的上一个节点
head
.
next
=
pre
;
//上一个已经反转到头部的节点
pre
=
head
;
//一直向链表尾走
head
=
next
;
}
return
pre
;
}
}
```
### 三 合并两个排序的链表
#### **题目描述:**
输入两个单调递增的链表,输出两个链表合成后的链表,当然我们需要合成后的链表满足单调不减规则。
#### **问题分析:**
我们可以这样分析:
1.
假设我们有两个链表 A,B;
2.
A的头节点A1的值与B的头结点B1的值比较,假设A1小,则A1为头节点;
3.
A2再和B1比较,假设B1小,则,A1指向B1;
4.
A2再和B2比较。。。。。。。
就这样循环往复就行了,应该还算好理解。
#### **考察内容:**
链表+代码的鲁棒性
#### **示例代码:**
**非递归版本:**
```
java
/*
public class ListNode {
int val;
ListNode next = null;
ListNode(int val) {
this.val = val;
}
}*/
public
class
Solution
{
public
ListNode
Merge
(
ListNode
list1
,
ListNode
list2
)
{
//list1为空,直接返回list2
if
(
list1
==
null
){
return
list2
;
}
//list2为空,直接返回list1
if
(
list2
==
null
){
return
list1
;
}
ListNode
mergeHead
=
null
;
ListNode
current
=
null
;
//当list1和list2不为空时
while
(
list1
!=
null
&&
list2
!=
null
){
//取较小值作头结点
if
(
list1
.
val
<=
list2
.
val
){
if
(
mergeHead
==
null
){
mergeHead
=
current
=
list1
;
}
else
{
current
.
next
=
list1
;
//current节点保存list1节点的值因为下一次还要用
current
=
list1
;
}
//list1指向下一个节点
list1
=
list1
.
next
;
}
else
{
if
(
mergeHead
==
null
){
mergeHead
=
current
=
list2
;
}
else
{
current
.
next
=
list2
;
//current节点保存list2节点的值因为下一次还要用
current
=
list2
;
}
//list2指向下一个节点
list2
=
list2
.
next
;
}
}
if
(
list1
==
null
){
current
.
next
=
list2
;
}
else
{
current
.
next
=
list1
;
}
return
mergeHead
;
}
}
```
**递归版本:**
```
java
public
ListNode
Merge
(
ListNode
list1
,
ListNode
list2
)
{
if
(
list1
==
null
){
return
list2
;
}
if
(
list2
==
null
){
return
list1
;
}
if
(
list1
.
val
<=
list2
.
val
){
list1
.
next
=
Merge
(
list1
.
next
,
list2
);
return
list1
;
}
else
{
list2
.
next
=
Merge
(
list1
,
list2
.
next
);
return
list2
;
}
}
```
\ No newline at end of file
docs/dataStructures-algorithms/算法题解析/剑指offer/(5)栈变队列和栈的压入、弹出序列.md
已删除
100644 → 0
浏览文件 @
7f506299
### 一 用两个栈实现队列
#### **题目描述:**
用两个栈来实现一个队列,完成队列的Push和Pop操作。 队列中的元素为int类型。
#### 问题分析:
先来回顾一下栈和队列的基本特点:
**栈:**
后进先出(LIFO)
**队列:**
先进先出
很明显我们需要根据JDK给我们提供的栈的一些基本方法来实现。先来看一下Stack类的一些基本方法:
![
Stack类的一些常见方法
](
http://my-blog-to-use.oss-cn-beijing.aliyuncs.com/18-4-4/5985000.jpg
)
既然题目给了我们两个栈,我们可以这样考虑当push的时候将元素push进stack1,pop的时候我们先把stack1的元素pop到stack2,然后再对stack2执行pop操作,这样就可以保证是先进先出的。(负[pop]负[pop]得正[先进先出])
#### 考察内容:
队列+栈
#### 示例代码:
```
java
//左程云的《程序员代码面试指南》的答案
import
java.util.Stack
;
public
class
Solution
{
Stack
<
Integer
>
stack1
=
new
Stack
<
Integer
>();
Stack
<
Integer
>
stack2
=
new
Stack
<
Integer
>();
//当执行push操作时,将元素添加到stack1
public
void
push
(
int
node
)
{
stack1
.
push
(
node
);
}
public
int
pop
()
{
//如果两个队列都为空则抛出异常,说明用户没有push进任何元素
if
(
stack1
.
empty
()&&
stack2
.
empty
()){
throw
new
RuntimeException
(
"Queue is empty!"
);
}
//如果stack2不为空直接对stack2执行pop操作,
if
(
stack2
.
empty
()){
while
(!
stack1
.
empty
()){
//将stack1的元素按后进先出push进stack2里面
stack2
.
push
(
stack1
.
pop
());
}
}
return
stack2
.
pop
();
}
}
```
### 二 栈的压入、弹出序列
#### **题目描述:**
输入两个整数序列,第一个序列表示栈的压入顺序,请判断第二个序列是否为该栈的弹出顺序。假设压入栈的所有数字均不相等。例如序列1,2,3,4,5是某栈的压入顺序,序列4,5,3,2,1是该压栈序列对应的一个弹出序列,但4,3,5,1,2就不可能是该压栈序列的弹出序列。(注意:这两个序列的长度是相等的)
#### **题目分析:**
这道题想了半天没有思路,参考了Alias的答案,他的思路写的也很详细应该很容易看懂。
作者:Alias
https://www.nowcoder.com/questionTerminal/d77d11405cc7470d82554cb392585106
来源:牛客网
【思路】借用一个辅助的栈,遍历压栈顺序,先讲第一个放入栈中,这里是1,然后判断栈顶元素是不是出栈顺序的第一个元素,这里是4,很显然1≠4,所以我们继续压栈,直到相等以后开始出栈,出栈一个元素,则将出栈顺序向后移动一位,直到不相等,这样循环等压栈顺序遍历完成,如果辅助栈还不为空,说明弹出序列不是该栈的弹出顺序。
举例:
入栈1,2,3,4,5
出栈4,5,3,2,1
首先1入辅助栈,此时栈顶1≠4,继续入栈2
此时栈顶2≠4,继续入栈3
此时栈顶3≠4,继续入栈4
此时栈顶4=4,出栈4,弹出序列向后一位,此时为5,,辅助栈里面是1,2,3
此时栈顶3≠5,继续入栈5
此时栈顶5=5,出栈5,弹出序列向后一位,此时为3,,辅助栈里面是1,2,3
….
依次执行,最后辅助栈为空。如果不为空说明弹出序列不是该栈的弹出顺序。
#### **考察内容:**
栈
#### **示例代码:**
```
java
import
java.util.ArrayList
;
import
java.util.Stack
;
//这道题没想出来,参考了Alias同学的答案:https://www.nowcoder.com/questionTerminal/d77d11405cc7470d82554cb392585106
public
class
Solution
{
public
boolean
IsPopOrder
(
int
[]
pushA
,
int
[]
popA
)
{
if
(
pushA
.
length
==
0
||
popA
.
length
==
0
)
return
false
;
Stack
<
Integer
>
s
=
new
Stack
<
Integer
>();
//用于标识弹出序列的位置
int
popIndex
=
0
;
for
(
int
i
=
0
;
i
<
pushA
.
length
;
i
++){
s
.
push
(
pushA
[
i
]);
//如果栈不为空,且栈顶元素等于弹出序列
while
(!
s
.
empty
()
&&
s
.
peek
()
==
popA
[
popIndex
]){
//出栈
s
.
pop
();
//弹出序列向后一位
popIndex
++;
}
}
return
s
.
empty
();
}
}
```
\ No newline at end of file
编辑
预览
Markdown
is supported
0%
请重试
或
添加新附件
.
添加附件
取消
You are about to add
0
people
to the discussion. Proceed with caution.
先完成此消息的编辑!
取消
想要评论请
注册
或
登录