PYTHON 从入门到精通-利用selenium 如何爬取网站数据

一、爬取豆瓣电影td数据代码

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
#-*- coding:UTF-8 -*-

# selenium对豆瓣页面进行操作

import urllib.request
from selenium import webdriver
def print_hi(name):
# Use a breakpoint in the code line below to debug your script.
print(f'Hi, {name}') # Press Ctrl+F8 to toggle the breakpoint.


# Press the green button in the gutter to run the script.

#Main函数入口
if __name__ == '__main__':
browser = webdriver.Chrome()
browser.get('https://movie.douban.com/')
tagname = browser.find_elements_by_tag_name('td')

for item in tagname:
try:
int(item.text) # 这一句出现异常时

except Exception:
print(item.text) # 将会走这一步

二、爬取豆瓣电影-轮播图中数据的href数据

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
#找到相应的轮播图数据的href
# This is a sample Python script.

# Press Shift+F10 to execute it or replace it with your code.
# Press Double Shift to search everywhere for classes, files, tool windows, actions, and settings.

import urllib.request
from selenium import webdriver
def print_hi(name):
# Use a breakpoint in the code line below to debug your script.
print(f'Hi, {name}') # Press Ctrl+F8 to toggle the breakpoint.


# Press the green button in the gutter to run the script.
#Main函数入口
if __name__ == '__main__':
browser = webdriver.Chrome()
browser.get('https://movie.douban.com/')
tagnames = browser.find_elements_by_class_name('list-wp') # 找到class为cover-wp所在的标签
for container in tagnames:
items = container.find_elements_by_class_name('slide-page') # 所有的slide-page
for item in items:
tag = item.find_elements_by_tag_name('a') # 找到每一个slide-page的a标签
print(len(tag))
for Tag in tag: # 每一个a标签的 href属性
print(Tag.get_property('href'))

# See PyCharm help at https://www.jetbrains.com/help/pycharm/

PYTHON 从入门到精通-类Class

类的定义:

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
class CLASS_NAME:
attr1 = 0
# 构造函数__init__
def __init__(self, param1, param2...): # self相当于C++中的this对象
self.param1 = param1
...

# 成员函数 将变量attr1加一
def fun(self):
attr1 += 1

# 类方法 调用时直接用CLASSNAME.set_attr_for_all
@classmethod
def set_attr_for_all(cls, attr1):
cls.attr1 = attr1

# 静态方法 一般写不涉及到某个对象 或者类的相关属性或者方法
@staticmethod
def hello_class():
print('Hello World!')

# 创建并初始化对象
class1 = CLASS_NAME()

# class1.xxx 代表对象实例的变量 或者 方法

# CLASS_NAME.xxx 代表类的变量或者方法

类的继承

比如有一个类:Human,另外有一个Student类 现在用Student类继承于Human

1
2
3
4
# Human类的构造函数:
class Human:
def __init__(self, name):
self.name = name
1
2
3
4
5
6
7
8
# Student比Human类多一个属性studentnum 
# 而从父类继承来的name属性 可以通过父类的构造方法进行构造
class Student(Human):
def __init__(self, name, studentnum):

# 利用父类的构造方法 构造name属性
super.class().__init__(name)
self.studentnum = studentnum

从零基础创建Springboot_Thymelear_layui项目

第一步:打开idea创建项目

在这里插入图片描述
直接点next下一步;

在这里插入图片描述
next点完,依赖后面再添加。

依赖删除,重新添加
①:spring-boot-starter-web
②:spring-boot-starter-thymeleaf

创建默认页面static和templates文件夹

1、其中 static 放除pages以外的
2、templates 放pages
(数据来自ok-admin-master) 百度网盘有

在这里插入图片描述
存入之后,项目结构图为(记得加入index.html)
在这里插入图片描述

首先测试主页,编写controller访问index(涉及SpringMVC)

注意,启动时可能会报相应Test错误(由于改动了相应的依赖)

在这里插入图片描述
只需要删除相应Test文件即可
在这里插入图片描述

编写相应的Controller 写页面跳转即可
在这里插入图片描述

前端若iframe嵌套页面为404

则比如:iframe标签中,src属性为welcome
那么写一个Controller RequestMapping参数为”welcome” 直接返回相应的前端页面即可 避免404
看图:

在这里插入图片描述
在这里插入图片描述

一级菜单与二级菜单 在menu.json中

在这里插入图片描述
大致页面如下:

localhost:8080 或者 localhost:8080/index (默认欢迎页面为Index)

在这里插入图片描述

目录测试

第一步:下载插件(HEXO-TOC)

1
cnpm install hexo-toc --save

第二步:配置博客根目录下的_config.yml文件

1
2
toc:
maxdepth: 3

第三步:在文章相应位置引用目录

1
<!-- toc -->

Mybatis学习笔记(所有代码FROM SIKI学院)

Mybatis是什么?

MyBatis 本是apache的一个开源项目iBatis, 2010年这个项目由apache software foundation 迁移到了google code, 并且改名为MyBatis 。2013年11月迁移到Github。MyBatis是支持定制化 SQL、存储过程以及高级映射的优秀的持久层框架。 MyBatis 避免了几乎所有的 JDBC 代码和手动设置参数以及获取结果集。MyBatis 可以对配置和原生Map使用简单的 XML 或注解,将接口和 Java 的 POJOs(Plain Old Java Objects,普通的 Java对象)映射成数据库中的记录。总而言之MyBatis是一个轻量级简化数据库操作的框架。

Mybatis架构

在这里插入图片描述

Mybatis的配置文件(包括数据库连接,MapperXML配置文件位置)

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
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE configuration
PUBLIC "-//mybatis.org//DTD Config 3.0//EN"
"http://mybatis.org/dtd/mybatis-3-config.dtd">

<configuration>

<!-- 读取数据库连接的配置文件 -->
<properties resource="db.properties"/>

<!-- 推荐使用package包的形式来配置别名
包的形式会扫描主包及子包下的所有文件
以对象类名为别名,大小写不限,推荐使用小写
-->
<typeAliases>
<!-- <typeAlias type="com.sikiedu.bean.User" alias="user"/> -->
<package name="com.sikiedu.bean"/>
</typeAliases>

<!-- 在集成spring 不用environments这个property -->
<environments default="development">

<environment id="development">

<!-- 使用jdbc的事务 -->
<transactionManager type="JDBC"/>

<!-- 使用连接池 连接数据库 -->
<dataSource type="POOLED">
<!-- 注意下面的jdbc.driver在文件db.properties中: -->
<!-- 写法是:jdbc.driver=com.mysql.jdbc.Driver -->
<property name="driver" value="${jdbc.driver}"/>
<property name="url" value="${jdbc.url}"/>
<property name="username" value="${jdbc.username}"/>
<property name="password" value="${jdbc.password}"/>
</dataSource>
</environment>
</environments>

<!-- 配置映射器配置文件 XXX.xml 的位置 -->
<mappers>
<!-- <mapper resource="mapper/UserMapper.xml"/> -->
<!-- <mapper url="file:\\\D:\Work\Siki_edu\JavaEE\Teach\SSM框架\ssm_project\ssm_mybatis\src\mapper\UserMapper.xml"/> -->
<!-- <mapper class="com.sikiedu.mapper.UserMapper"/> -->
<!-- 推荐使用包的形式配置 -->
<package name="com.sikiedu.mapper"/>
</mappers>

</configuration>

注意:
当使用<package/>标签时 映射接口文件与映射配置文件共同应该在Mapper文件夹下

否则使用mapper标签 且用resource指定对应的配置文件所在目录

Mybatis某个映射接口文件以及对应的XML文件(比如UserMapper.java & UserMapper.xml)

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
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapper
PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
"http://mybatis.org/dtd/mybatis-3-mapper.dtd">

<!-- 注意域名namespace不要写错 相当于自己地址 -->
<mapper namespace="com.sikiedu.mapper.UserMapper">

<sql id="myselect">
SELECT *
FROM user
</sql>

<!-- 根据id查询用户 -->
<!-- 注意! 标签中的id属性值,必须与对应Mapper接口文件中的方法名一致!!! -->
<select id="selectUserById" parameterType="Integer" resultType="user">
select * from user where u_id = #{id}
</select>

<!-- 根据名字模糊查询用户 -->
<!-- #{} 占位符 尽量选用#{}来解决问题 '1' '王'-->
<!-- ${} 字符串拼接 or 1=1 王 -->
<!-- order by ${} -->
<select id="selectUserByName" parameterType="String" resultType="com.sikiedu.bean.User">
<!-- SELECT * FROM USER WHERE u_username LIKE '%${value}%' -->
SELECT * FROM USER WHERE u_username LIKE "%"#{name}"%"
</select>

<!-- 添加用户 -->
<insert id="insertUser" parameterType="com.sikiedu.bean.User">
insert into user values( null, #{u_username} , #{u_password}, #{u_sex}, #{u_createTime}, #{u_cid} )
</insert>

<!-- 修改用户 -->
<update id="updateUser" parameterType="com.sikiedu.bean.User" >
update user set u_username = #{u_username} where u_id = #{u_id}
</update>

<!-- 根据id删除用户 -->
<delete id="deleteUserById" parameterType="Integer">
delete from user Where u_id = #{id}
</delete>

<select id="selectUserByUserVoId" parameterType="UserVo" resultType="user">
select * from user where u_id = #{user.u_id}
</select>

<!-- public Integer selectUserCount(); -->
<select id="selectUserCount" resultType="Integer">
Select Count(*) from user
</select>

<!-- public List<UserVo> selectAllUserVo(); //查询所有用户包装类 -->
<resultMap type="UserVo" id="uservolist">
<id property="u_id" column="u_id"/>
<result property="u_username" column="u_username"/>
<result property="u_sex" column="u_sex"/>
<association property="country" javaType="Country">
<id property="id" column="c_id"/>
<result property="c_countryname" column="c_countryname"/>
</association>
</resultMap>
<select id="selectAllUserVo" resultMap="uservolist">
SELECT
u.`u_id`,
u.`u_username`,
u.`u_sex`,
c.`c_id`,
c.`c_countryname`
FROM USER u
LEFT JOIN
country c
ON u.`u_cid`=c.`c_id`
</select>

<!-- //多条件查询 通过用户对象中的条件查询用户列表
public List<User> selectUserListByUser(User u); -->

<select id="selectUserListByUser" parameterType="User" resultType="User">
<!-- 查询用户性别 模糊查询用户名 查询用户cid 国籍ID -->
SELECT *
FROM user
<where>
<!-- where标签可以去掉开头的AND -->
<if test="u_sex != null and u_sex != ''">
AND u_sex = #{u_sex}
</if>
<if test="u_username != null and u_username != ''">
AND u_username like "%"#{u_username}"%"
</if>
<if test="u_cid != null">
AND u_cid = #{u_cid}
</if>
</where>
</select>

<select id="selectUserListByUserTrim" parameterType="User" resultType="User">
<!-- 查询用户性别 模糊查询用户名 查询用户cid 国籍ID -->
SELECT *
FROM user
<trim prefix="where" suffixOverrides="AND">
<!-- where标签可以去掉开头的AND -->
<if test="u_sex != null and u_sex != ''">
u_sex = #{u_sex} AND
</if>
<if test="u_username != null and u_username != ''">
u_username like "%"#{u_username}"%" AND
</if>
<if test="u_cid != null">
u_cid = #{u_cid} AND
</if>
</trim>
</select>

<!-- public void updateSetUser(User u); -->
<update id="updateSetUser" parameterType="User">
<!-- 用户名 用户密码 性别 用id来限制 -->
update user
<set>
<if test="u_username != null and u_username != ''">
u_username = #{u_username},
</if>
<if test="u_password != null and u_password != ''">
u_password = #{u_password},
</if>
<if test="u_sex != null and u_sex != ''">
u_sex = #{u_sex}
</if>
</set>
Where u_id = #{u_id}
</update>

<!-- //使用多个id获取用户列表
public List<User> selectUserListByIds(); (1, 3, 5)-->
<select id="selectUserListByIds" resultType="User">
SELECT *
FROM USER
WHERE u_id
IN
<!-- (1,2,3) -->
<foreach collection="array" item="id" open="(" close=")" separator=",">
#{id}
</foreach>
</select>

<!-- //使用多个id获取用户列表
public List<User> selectUserListByIds(); (1, 3, 5)-->
<select id="selectUserListByList" resultType="User">
SELECT *
FROM USER
WHERE u_id
IN
<!-- (1,2,3) -->
<foreach collection="list" item="id" open="(" close=")" separator=",">
#{id}
</foreach>
</select>

<!-- List<User> selectUserByVo(CountryVo vo); -->
<select id="selectUserByVo" parameterType="CountryVo" resultType="User">
<include refid="myselect"/>
WHERE u_id
IN
<!-- (1,2,3) -->
<foreach collection="list" item="id" open="(" close=")" separator=",">
#{id}
</foreach>
</select>

<!-- //使用多个id获取用户列表 by userVO
public List<User> selectUserListByUserVo(UserVo vo); -->
<select id="selectUserListByUserVo" parameterType="UserVo" resultType="User">
<include refid="myselect"/>
WHERE u_id
IN
<!-- (1,2,3) -->
<foreach collection="idList" item="id" open="(" close=")" separator=",">
#{id}
</foreach>
</select>


</mapper>

在Mybatis中的(XXXMapper.xml)映射文件中需要注意的事项

  1. namespace 代表该映射文件的域名地址 不要填错
  2. select标签中的id 必须与对应Mapper.java文件中的方法名一致!!!
  3. parameterType 代表接口中方法的形参类型 要一致
  4. resultType代表返回类型,以下两者均可 要一致
    (com.sikiedu.bean.User是全称)
    (user是Mybatis配置文件中配置好的 TypeAlias起的别名)
  5. 具体的SQL语句中 #{x} 的x代表UserMapper接口文件中形参名 要一致

UserMapper.java文件(映射接口文件)

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
package com.sikiedu.mapper;

import java.util.List;

import com.sikiedu.bean.User;
import com.sikiedu.bean.UserVo;

public interface UserMapper {

//mapper动态代理开发四大原则 + 一个注意
//1、接口方法名需要与mapper.xml的要调用的sql语句的id一致
//2、接口的形参类型需要与mapper.xml parameterType 一致
//3、接口的返回值需要与mapper.xml resultType一致
//4、mapper.xml 中namespace要与接口的全包名一致
//5、注意mapper动态代理开发中,根据返回值类型来自动选择

//通过id查询一个用户
public User selectUserById(Integer id);

//通过用户名模糊查询 获取用户列表
public List<User> selectUserByName(String name);

//通过UserVo id查询一个用户
public User selectUserByUserVoId(UserVo vo);

//查询用户总条数
public Integer selectUserCount();

//查询所有用户包装类
public List<UserVo> selectAllUserVo();

//多条件查询 通过用户对象中的条件查询用户列表
public List<User> selectUserListByUser(User u);

//多条件查询 通过用户对象中的条件查询用户列表Trim
public List<User> selectUserListByUserTrim(User u);

//更新用户表
public void updateSetUser(User u);

//使用多个id获取用户列表 by array
public List<User> selectUserListByIds(Integer[] ids);

//使用多个id获取用户列表 by list
public List<User> selectUserListByList(List<Integer> idList);

//使用多个id获取用户列表 by userVO
public List<User> selectUserListByUserVo(UserVo vo);
}

与数据库中相对应的实体类文件(XXX.java)

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
package com.sikiedu.bean;

import java.util.Date;

public class User {

/**
* CREATE TABLE `user` (
`u_id` INT(11) NOT NULL AUTO_INCREMENT COMMENT '用户id',
`u_username` VARCHAR(64) NOT NULL COMMENT '用户名',
`u_password` VARCHAR(64) NOT NULL COMMENT '用户密码',
`u_sex` VARCHAR(16) DEFAULT NULL COMMENT '用户性别',
`u_createTime` DATETIME DEFAULT NULL COMMENT '用户创建时间',
`u_cid` INT(11) NOT NULL COMMENT '用户国家id',
*/

private Integer u_id;
private String u_username;
private String u_password;
private String u_sex;
private Date u_createTime;
private Integer u_cid;

public Integer getU_id() {
return u_id;
}
public void setU_id(Integer u_id) {
this.u_id = u_id;
}
public String getU_username() {
return u_username;
}
public void setU_username(String u_username) {
this.u_username = u_username;
}
public String getU_password() {
return u_password;
}
public void setU_password(String u_password) {
this.u_password = u_password;
}
public String getU_sex() {
return u_sex;
}
public void setU_sex(String u_sex) {
this.u_sex = u_sex;
}
public Date getU_createTime() {
return u_createTime;
}
public void setU_createTime(Date u_createTime) {
this.u_createTime = u_createTime;
}
public Integer getU_cid() {
return u_cid;
}
public void setU_cid(Integer u_cid) {
this.u_cid = u_cid;
}
@Override
public String toString() {
return "User [u_id=" + u_id + ", u_username=" + u_username + ", u_password=" + u_password + ", u_sex=" + u_sex
+ ", u_createTime=" + u_createTime + ", u_cid=" + u_cid + "]";
}
}

  1. 推荐类名的私有变量的名字完全与数据库中字段名相同
  2. 给相应Set、Get方法即可
  3. toString方法

函数如何调用完整的Mybatis过程(增删改查)

一、selectOne 函数(查询)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
@Test
//入门程序 通过ID 查询用户
public void Test1() throws IOException {
String resource = "sqlMapConfig.xml";

//读取配置文件
InputStream in = Resources.getResourceAsStream(resource);

//需要sqlSessionFactoryBulider
SqlSessionFactoryBuilder ssfb = new SqlSessionFactoryBuilder();

//创建sqlSessionfactory
SqlSessionFactory ssf = ssfb.build(in);

//生产一个sqlSession
SqlSession session = ssf.openSession();

//操作数据库
//参数1:要操作的接口方法 参数2 sql语句的参数
User user = session.selectOne("UserMapper.selectUserById", 1);
System.out.println(user);
}

二、session的getMapper方法 找到Dao层接口类(查询)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
String resource = "sqlMapConfig.xml";

//读取配置文件
InputStream in = Resources.getResourceAsStream(resource);
//需要sqlSessionFactoryBulider
SqlSessionFactoryBuilder ssfb = new SqlSessionFactoryBuilder();
//创建sqlSessionfactory
SqlSessionFactory ssf = ssfb.build(in);

//将IUser加入工厂中 以getMapper找到
sqlSessionFactory.getConfiguration().addMapper(IUser.class);
SqlSession session = sqlSessionFactory.openSession();

try {
//通过getMapper方法 找到IUser接口类
IUser iuser = session.getMapper(IUser.class);
//调用相应方法(增删改查)
User user = iuser.getUserByID(1);
System.out.println("名字:"+user.getName());
} finally {
session.close();
}

Mybatis的调用过程中:

  1. 首先需要输入流 读取配置文件sqlMapConfig.xml
  2. 需要一个工厂建造者Builder 来利用这个输入流建造
  3. 建造返回一个工厂 用这个工厂打开一次会话
  4. 在会话中Select…等等
  5. 对于更改操作(插入、更新、删除)记得session.commit()
  6. session的对应方法 第一个参数是通过XXXMapper.对应方法 第二个是传入的实参

三、session的getMapper方法 找到Dao层接口类(插入)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
....忽略配置文件加载、SQLSession建造者、工厂....

try {
//通过getMapper方法 找到IUser接口类
IUser iuser = session.getMapper(IUser.class);

//假设该接口类有 void方法insertUser(User user)
User user = new User();
user.setXXX("xxx");
...set方法

//插入数据 记得提交会话(包括删除操作、更新操作)
iuser.insertUser(user);
session.commit();

} finally {
session.close();
}

四、session的getMapper方法 找到Dao层接口类(更新)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
....忽略配置文件加载、SQLSession建造者、工厂....

try {
//通过getMapper方法 找到IUser接口类
IUser iuser = session.getMapper(IUser.class);

//首先通过相应属性找到user
User user = iuser.getUserById(1);

//假设该接口类有 void方法updateUser(User user)
//将user的name更改为Vincent
user.setName("Vincent");

//更新数据 记得提交会话
iuser.updateUser(user);
session.commit();

} finally {
session.close();
}

五、session的getMapper方法 找到Dao层接口类(删除)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
....忽略配置文件加载、SQLSession建造者、工厂....

try {
//通过getMapper方法 找到IUser接口类
IUser iuser = session.getMapper(IUser.class);

//首先通过相应属性找到user
User user = iuser.getUserById(1);

//假设该接口类有方法 deleteUser(User user)
//记得提交会话

iuser.deleteUser(user);
session.commit();

} finally {
session.close();
}

ResultMap:解决数据库字段与Java实体类的属性不一致问题

1.Result实现JavaBean对象与数据库column名字不一样的映射

1
2
3
4
5
6
7
8
9
10
<!-- type表示具体的Java类 id随便取-唯一标识即可 -->
<resultMap type="CountryVo" id="countryVo">

<!-- id标签是主键 property是Java类中的属性 column是对应Java类在数据库表中的字段 -->
<id property="id" column="c_id"/>

<!-- result可以是若干个其他 非主键属性的对应 -->
<result property="c_countryname" column="c_countryname"/>
<result property="c_capital" column="c_capital"/>
</resultMap>

2.Result实现一对多映射 Collection

比如一个用户User 有多个帖子Post
现在查询对应的User 查看这个User下的所有帖子(因此帖子是集合java private List<Post> posts;)

1.User类

1
2
3
4
5
6
7
8
9
10
11
12

//要实现序列化Serializable
public class User implements Serializable{
private int id;
private String username;
private String mobile;

//一个User 对应多个Post 因此用集合
private List<Post> posts;

...忽略set get方法以及toString方法
}

2.Post类

1
2
3
4
5
6
7
8
public class Post implements Serializable{
//查询的时候 post.id 应该等于 user.id
private int id;
private User user;
private String title;
private String content;
...忽略set get方法以及toString方法
}

3.ResultMap配置一个用户多个帖子的映射

1
2
3
4
5
6
7
8
9
10
11
12
13
<!-- 在一个User中配置 多个collection -->
<resultMap type="User" id="resultUserMap">
<result property="id" column="user_id" />
<result property="username" column="username" />
<result property="mobile" column="mobile" />
<!-- collection代表多 -->
<!-- posts代表User类中 集合的名字!column代表post表中的那个字段 与user联系 -->
<collection property="posts" ofType="com.yiibai.pojo.Post" column="userid">
<id property="id" column="post_id" javaType="int" jdbcType="INTEGER"/>
<result property="title" column="title" javaType="string" jdbcType="VARCHAR"/>
<result property="content" column="content" javaType="string" jdbcType="VARCHAR"/>
</collection>
</resultMap>

4.SQL语句

1
2
3
4
5
6
7
8
<!-- 指定结果映射为resultUserMap 需要跟相应resultMap标签的id相同 -->
<select id="getUser" resultMap="resultUserMap" parameterType="int">
<!-- 建立映射就是为了 能够映射SELECT后面的内容:u.*, p.* -->
<!-- 没有建立映射的property返回的值不会显示在后台里 -->
SELECT u.*,p.*
FROM user u, post p
WHERE u.id=p.userid AND id=#{user_id}
</select>

2021.4.6更新:

  1. 注意都实现Serializable接口
  2. 注意,如果两张表中的字段重复了,记得在Select字段中起别名
  3. collection中的id标签 不会指两者映射的id 而只是指这个表的主键!
  4. 真正映射一对多的 是collection中的column属性

起别名代码:

1
2
3
4
5
6
<select>
select u.id as u_id, u.*, p.id as p_id,p.*
from user u, post p
where u.u_id = p.p_id AND u.u_id = #{id}
</select>

Mybatis_plust新特性:代码生成器

注意,这里的代码指的是:

1. DAO层的XXXMapper.java接口
2. DAO层的XXXMapper.xml文件
3. Model层的XXXExample.java类 方便提前处理数据

1.需要的插件(IDEA右侧 MAVEN里面的插件双击启动)

1
2
3
4
5
6
7
8
9
10
<plugin>
<groupId>org.mybatis.generator</groupId>
<artifactId>mybatis-generator-maven-plugin</artifactId>
<configuration>
<configurationFile>${basedir}/src/main/resources/mybatis-generator/generatorConfig.xml
</configurationFile>
<overwrite>true</overwrite>
<verbose>true</verbose>
</configuration>
</plugin>

项目结构图:

在这里插入图片描述

2.配置文件 generatorConfig.xml

这一步很关键,要避免多次生成重复的BaseResultMap

注意对应Mapper.java/ Mapper.xml在项目结构图中的位置

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
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE generatorConfiguration
PUBLIC "-//mybatis.org//DTD MyBatis Generator Configuration 1.0//EN"
"http://mybatis.org/dtd/mybatis-generator-config_1_0.dtd">

<generatorConfiguration>

<!-- 连接数据库jar包的路径-->
<classPathEntry location="C:\Users\Administrator\.m2\repository\mysql\mysql-connector-java\8.0.23/mysql-connector-java-8.0.23.jar"/>

<context id="DB2Tables" targetRuntime="MyBatis3">
<commentGenerator>
<property name="suppressDate" value="true"/>
<!-- 是否去除自动生成的注释 true:是 : false:否 -->
<property name="suppressAllComments" value="true"/>
</commentGenerator>

<!--数据库连接参数 -->
<jdbcConnection
driverClass="com.mysql.jdbc.Driver"
connectionURL="jdbc:mysql://localhost:3306/vue_demo?serverTimezone=UTC&amp;useSSL=true"
userId="root"
password="123456">
<!-- 避免生成重复的BaseResultMap -->
<property name="nullCatalogMeansCurrent" value="true" />
</jdbcConnection>

<javaTypeResolver>
<property name="forceBigDecimals" value="false"/>
</javaTypeResolver>

<!-- 实体类的包名和存放路径 -->
<javaModelGenerator targetPackage="com.example.demo.entity" targetProject="src/main/java">
<property name="enableSubPackages" value="true"/>
<property name="trimStrings" value="true"/>
</javaModelGenerator>

<!-- 生成映射文件*.xml的位置-->
<sqlMapGenerator targetPackage="mybatis" targetProject="src/main/resources">
<property name="enableSubPackages" value="true"/>
</sqlMapGenerator>

<!-- 生成DAO的包名和位置 -->
<javaClientGenerator type="XMLMAPPER" targetPackage="com.example.demo.repository" targetProject="src/main/java">
<property name="enableSubPackages" value="true"/>
</javaClientGenerator>

<!-- tableName:数据库中的表名或视图名;domainObjectName:生成的实体类的类名-->
<!--<table tableName="book" domainObjectName="Book"/>-->
<table schema="catalog" tableName="user" domainObjectName="User"/>

</context>
</generatorConfiguration>

Mybatis中出现的问题:

1.UserMapper.xml到底应该放在那里?

注意,在集成SpringBoot时

  1. 首先确保 UserMapper.java要有@Mapper注解

  2. 其次,要注意在SpringBoot配置文件application.yml中:

1
2
mybatis:
mapper-locations: classpath:mybatis/*.xml

并且项目结构图如下:
在这里插入图片描述

  1. UserMapper.xml中的namespace是UserMapper.java的具体位置

或者代码generator生成的配置文件中配置

1
2
<mapper namespace="com.example.demo.repository.UserMapper"> 
</mapper>

配置实体类应该注意的问题

1. 尽量让实体类中的各个private属性名字与数据库的字段名字相同

2. 用封装类!不要用int,而是应该用Integer

3. 如果实体类中的属性名与数据库中的字段名相同,这样mapper中参数为实体类时,才能返回

不会吧?都2021年了,还有人觉得考研英语简单!?

刚过线低分学长考研英语做题方法分享(全是干货)你还在等什么?等我吗?:

作者前言

    
考研英语分为英语一与英语二,其中英语一多为学术型研究生而准备,而英语二多为专业型研究生而准备。本文旨在总结考研一路走来自己对英语二学科的重要总结以及经验之谈比较适合在经过一段真题复习之后抓重点、查漏补缺!希望阅读到本文的你能够有所得。Respect!

一、完形填空 Use of English


    完形填空,一直都是大家不重视的科目,毕竟所占的分数不多,才 “十分”,但是非常重要!(请大家务必重视完形的做题方法)万事开头难,完形也不例外。

Without further ado 废话不多说,我们直接进入正题~

    以下笔记以及方法论,自己总结归纳众多名师(其实没怎么看他们本人的课,都在各个网络渠道微博,知乎,哔哩哔哩等看到的方法哈哈哈)

完形填空我建议同学去读读 刘晓燕老师的《真题就这么点儿事》有道的赵楠楠老师的相关教学,正文开始!

1.读懂前两句/段,即读懂文章的 中心主旨句


读懂文章所围绕写的中心,同时联系作者自身的态度!这一步能否做到,能决定你是否读懂文章大致走向(**同时也是阅读理解做题步骤中,关键的一步!后话。**)

例如:(2015年英语二文章)
==In our contemporary culture== , the prospect of communicating with-or even looking at- a stranger is virtually unberable. ==Everyone== around us seems to ==agree== by the way they cling to their phones, even without a __ on a subway.

第一句指出,当代文化(=大众 everyone)认为,与陌生人交谈,甚至看向陌生人都是不可忍受的, // 而作者的观点, 大多“反对”大众文化。

我们看看第二段怎莫硕呢:

==It’s a sad reality== —our desire to avoid interacting with other human beings—because there’s___to be gained from talking to the stranger standing by you.

“sad”表明作者对此观点表示批判(小技巧:附有鲜明态度的形容词,一般很好地体现出作者的态度),同时==表明自己的观点(与大众相反即可):看向陌生人,与陌生人交谈其实没那么难以忍受。==

在知道作者的观点与态度或者文章的主旨句之后,再去斟酌每个选项,也许可以从更宏观的方面去把握更正确更优的答案。

我们再来看个例子:(2013年英语二文章)

Given the advantages of electronic money,==you might think== that we would move quickly to the cashless society in which all payments are made electronically. ___, a ==true== cashless society ==is probably not around the corner==.

如出一辙,you might think = 大众的观点,即认为很快会进入“无纸化社会”,而后提到真正的无纸化社会也许还没有到来,明显提出自己的观点。因此,全文的选项,选择时都应该按照 无纸化不会到来 这个大方向来做。


2.具体填空处前后“词语”的逻辑关系


例如:(2018年英语二文章)

The drive to discover is deeply rooted in humans, much the same as the basic drives for __ or shelter.

该文章主要说明:为什么人们总是在网上浏览很负能量的评论,做一些明显很令人痛苦的事情。因为人们习惯去解决“不确定”,可能明知到事情的答案,还是想满足自己内心的好奇心。

而聚焦到问题,说人类探索未知的渴求,如同探求__或避难所(庇护)一样,或者所连接的前后意思相近

A.Food (食物) B.pay(工资) C.Marriage(婚姻) D.schooling(学校教育)
根据排除法和常识,我们可以确定答案选 A,与 shelter 避难所含义相近。

譬如active 与 alive 也是具有相同意义的词语。

若文章的中心是反对战争支持和平,那么若某一细节处出现 *** ___war *** 选项中优先考虑 against等表示反对的介词.

3.具体填空处前后“语句”的逻辑关系


例如:(2013年英语二文章)

Given the advantages of electronic money,==you might think that we would move quickly to the cashless society in which all payments are made electronically.== ___, ==a true cashless society is probably not around the corner==.

您也许会认为我们很快会进入无纸化社会,但是真正的无纸化社会也许可能不会很快来到。根据插入语(即填空处)前后的逻辑关系,属于虽然但是(让步状语从句),且转折处为作者观点,是重点!聚集选项:

A. However (然而)
B. Moreover (而且)
C. Therefore (因此)
D. Othervise (否则)

同样地,对于:
1.总分结构再次强调作者观点句的:For instance, for example,

4.与文章背景相关(context-oriented)的单词更容易成为正确选项


例如:(2013年英语二文章)

在这里插入图片描述
Dishonest persons 可能会进入电子支付系统并__某人的账户,本文所讲的是无纸化社会不会到了,也就是说作者对无纸化社会的态度是negative的,因而我们首先判断这个动词的褒贬方向:是好的方向,还是坏的方向; 既然针对 “electronic payments system” 那么代表坏的方向,因而我们聚焦到选项:
在这里插入图片描述
A. 偷窃,盗取
B. 选择
C. 使受益
D. 返回,收益(pl)

了解到出题者的用心良苦后,我想答案不言而喻。

5.填空之处前后的固定搭配&词组辨析


例如:2015年英语二真题!

在这里插入图片描述
文章在此处阐述,与其与陌生人交谈,倒不如自己在乘车时独自闭口不谈,而在经历实验之后,大家没有觉得 “与陌生人交谈”让人尴尬。

聚焦选项:
在这里插入图片描述
go through with 经历 do away with 终结,废除 catch up with 追赶 put up with 容忍,忍受
这里用put up with是不恰当的,因为受实验者并没有完全谴责或者反对与陌生人交谈的行为。因为使用经历较好。

利用上文五大点,无论是宏观把握还是细节斟酌都能很好地选出最优答案,剩余的事情,就是从反复研读历年真题。找出选项与所在处前后的共性,不断总结归纳常考词汇。



二、阅读理解

1.个人认为,对于考研英语试卷而言,卷子的核心是阅读!阅读是值得我们反复研读的。


2.扎实的词汇基础,严谨的行文思路,最后辅佐于相对正确的小技巧。一定可以拿下高分!


对于英语而言,夯实词汇基础的重要性不言而喻,单词都不认识,更不用说读文章了。 市面上有太多太多的词汇书。

基础不太好的同学,建议跟相关老师的视频课,撇开阅读而谈词汇: 朱伟老师的词汇课挺不错的!何凯文老师的必考词汇也不错,有些推荐的单词是专八系列。从词汇本身的难度而言,是比较好的,附有相近词与例句。 建议基础较好的同学,可以不用听专门的词汇课,本人反复看《十天搞定考研词汇》再辅佐历年真题(真题词汇,建议自己总结!!!),可以达到一样的效果,

阅读方法正文:(本段以历年真题为例子)

拿到文章先看选项,只看选项即可(预热)


考研阅读板块,我建议跟名师:
1.有道唐迟老师、赵楠楠老师
2.前文都、现新文道教育何凯文老师

唐迟而言,串联题干而避免选项干扰 是对锁定文章内容、排除错误方向起着重要作用的。

看完选项后,根据零散的记忆,是否可以推测以下大致围绕什么主题讲。 经济?社会问题?现象?文化板块….

直接上题:2020年英语二真题Text1

第一问:
在这里插入图片描述
第二问:
在这里插入图片描述
第三问:
在这里插入图片描述
第四问:
在这里插入图片描述
第五问:
在这里插入图片描述
总览所有选项,几乎不离 Rat 老鼠 and Robot 机器人(文中的机器鼠) 单词,因而我们在读完题目之后。思考:
本文或许是阐述,有关于老鼠的实验,从实验中,我们应该找到:

1.具体人物表达的观点或态度

2.作者的态度/若无明显态度,则作者不反对的态度基本与作者态度一致

再读完题目后,回到文章本身,精读文章首段/首两段


熟悉吗?没错,就是完形填空的第一步!精读文章第一段,再对文章大致主题的主观推测基础上,用作者自己的话再次佐证文章的中心话题。譬如本文第一段:
在这里插入图片描述
第一句中,挑出比较重要的部分,to attuned to 意为 “ 适应,调整 或 对…敏感”。因此,开篇提到老鼠对社会信号高度敏感,以此来认清敌友。 因此纵观全文,作者应探讨老鼠与 “社会信号” 的关系。

再比如:2018年英语二Text2
在这里插入图片描述
这种以 “while” 引导的让步状语从句,是考研长句中比较普遍的句式。while 此时作 “尽管,虽然” 的意思,从句不重要!重要的是主句,即逗号后面的内容(未来属于例如风能、太阳能等新能源)这一句同时也是文章围绕讲的内容。因此作者既然说出来了未来是属于新能源的,那么作者对新能源应持正面,支持的态度!


细节题目怎么做?难,难在什么地方?


个人认为,只需要将文章分为:

1.主旨题, 2.细节题, 3.例证题 4.态度题

凡是不属于主旨题(中心思想,文章题目,文章大致内容)、例证题(某某例子说明什么?作者通过xx想表达什么?)以及态度题(不管是作者还是出现的某某某)的,都归于细节题,从文章某处本身上下文寻找最优答案。

看几个例子:
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

做法因人而异,但个人觉得比较适合大家的是:
1.通读全文,一顿勾勾画画
2.定位到相应的句子,读懂句子,联系中心!!!
3.找选项中错误的句子,找与关键句子同意替换的表达式
4.与文章中心靠拢!排除与中心相反或根本无关的句子

其中,2,3,4,是较为困难的过程,同时需要大量的反复练习。揣摩到底这个选项是不是符合中心内容的,是不是对的?哪里有相应同意的表达句,或者是不是正话反说?(出现过,概率不大)

仍然聚焦 2020年英语二 Text1:
在这里插入图片描述
Q与同事对老鼠进行测试是想看看老鼠是否会___?

明显属于细节题,看文章内容:
在这里插入图片描述
其中,蓝色划线句是文章背景句。而红色划线句是相应重点句,文章说:为了看看这种敏感程度是否会延伸到 “非动物”身上即:(老鼠是否会对来自机器鼠的社交信号而敏感),因而与选项中比对,是否有与其同意表达的,排除与中心内容无关的,排除说法相反的。

选项:
在这里插入图片描述
答案一定是来自文章的句子的,绝不是经过主观理解臆断出来的。 这是考研英语阅读不变应万变的宗旨。因而,A选项提到是否老鼠能够获得来自“机器鼠”的社交信号 ,即是细节句的同意表达。因而正确!因为是细节句的同意表达,因而在A选项的存在情况下,其他选项不具备更优答案的气质。

再举个例子:
2020年 Text4
在这里插入图片描述
M认为,相比较于 millennials(千禧一代)Z世代比较___?

根据定位出题处,
在这里插入图片描述
** 注意:题中问的Z世代如何?因此选项中可以排除千禧一代所具有的特点(flexible)。而文中提到因为零工经济 (gig economy) Z世代者寻求更多的确定性、稳定性 ,有这一关键句就够了。从选项中找“确定性” “稳定性” 的同义词,同时排除相反的词。聚焦选项:

在这里插入图片描述
A 更加勤奋 (中心无关)
B 更加慷慨(同理)
C 没那么追求实际 (相反含义应排除,因为正是零工经济,所以追求实际情况)
D 没那么冒险、比较谨慎 (more certainty、stability 的同义词 = 谨慎,不冒险)

因此,该类型的题目的核心点: 答案文中找,不找无关的,找同意替换、更贴近中心的。


例证题不找例子?那找什么?


相信听过唐迟老师课程的同学都知道, 例子不重要,重要的是例子所欲支撑的观点。 没错,我们的目的就是找例子前后的观点。说来简单,做来实属不易。

举个例子:2019年Text2
在这里插入图片描述
作者谈到 “艰难的挑战之一” ,何意?

回归文章:

在这里插入图片描述
句子很长,内容比较多。但是挑出与题目更直接相关的内容。可以看到,开篇作者提出森林给了我们庇护,给了我们在应对环境变化中出现的艰难挑战 ,fight against climate change 是好事情啊,为何提到是 challenge 挑战呢?原来,The climate change 会使得森林排放比自身吸收得更多的碳元素 = 入不敷出因而有了这一关键句就够了。做题时,抓住好事会变成坏事,找森林给了我们艰难挑战的同意表达:

在这里插入图片描述
在这里插入图片描述
相比较而言,森林给了我们艰难挑战对应同意表达的选项是
【B】forests may become a potential threat 森林有可能成为潜在的威胁 = 艰难挑战 = 排放出多于自身吸收的碳元素

再看一个例子:2021年 Text 2

在这里插入图片描述
L大学的报告显示,在英国,____

回归文章:

在这里插入图片描述
划线句子是关键句,根据报道,在英国,全国85%的土地与肉产品、奶制品直接相关。 读文章时,有些必要成分是一定要揣摩的,比如 “数字” “书名号” “感叹号” 作者不会无缘无故提到数字,不会无缘无故地提到某书的命名,同时也不会无缘无故地感叹、发表观点。

比如这里,文中出现 85% ,心中就要想,这个数字代表什么?想要强调什么?好事还是坏事?会不会与作者态度相关?

找到关键句后,回归选项:

[A] farmland has been inefficiently utilised
[B] factory style production needs reforming
[C] most land is used for meat and dairy production
[D] more green fields will be converted for farming

因而经过关键句的同意表达:85% percent = most land 再三斟酌,可以选出正确答案 C选项。

“主旨题” 约等于 ≈ 观点态度题?

文章的主旨就是整个文章的心脏,文章主旨当然大部分是与作者观点态度直接相关的。因而,做文章时,应首先明确自己的做题目标:

①、文章主旨/文章中心

②、作者观点(是否相同/相反)

这一块我还是力挺唐迟老师的做法:回文法。
如果给你ABCD四个标题,或者四个文章主旨,你会怎么写文章?

例如:2016年text3
在这里插入图片描述
直接看第一段,思考中心话题

在这里插入图片描述
每个人都太忙了,这已经是Cliche(陈词滥调,老生常谈)了。而抱怨声尤其来自:没时间阅读。 至此,我们已经可以猜测到,这篇文章是讲没时间阅读这个现象,作者一定会围绕这个中心话题展开探讨。

在这里插入图片描述
因而,答案一目了然。 How to Find Time to Read 如何空出时间来阅读? 这不就是中心话题吗?反过来说,如果是命题作文:如何空出时间阅读?

第一步当然就是陈述现象!阐述随着当今世界发展,越来越多的人哀嚎:没有时间阅读。然后继续行文…

再举个例子:

在这里插入图片描述
问作者态度,针对英国政府目前在运动方面所作出的努力。

回归文章:

在这里插入图片描述
The Parkrun phenomenon 本地公园跑现象的成功,更加凸显伦敦奥运遗风的失败!,为全文点出批评英国政府的总基调。作者提到:十年前,Planning documents 承诺人们会更苗条,更健康,然后事情并不如人意,Officials 并没有激励新一代更多地参与体育!

聚焦选项:
在这里插入图片描述
A 忍受,容忍
B 批判,批评
C 不确定的
D 同情的

根据作者所表达的态度,伦敦奥运遗风的失败! 批评英国政府的总基调, Officials 并没有激励新一代更多地参与体育! 我们可以确定,作者对英国政府持批评态度

三、新题型(阅读理解的“儿子”:定位-关键句-比对)


为什么这么说?很简单,不管是小标题题型(每段话缺标题,给出若干个标题,一一对应)
在这里插入图片描述
在这里插入图片描述

还是概括句题 (文章后有一个表格,将左边的事物与右边的表述一一正确对应)

在这里插入图片描述
均是在在阅读文章,完全理解了文章之后!对阅读到的信息进行归纳总结。

新题型板块,我建议:
有道赵楠楠老师

可以说对于两种题型,方法大同小异:

1.定位
2.找同义替换
3.回归选项

带着做题思路做真题,例如2018年小标题题型,放出链接如下:

2018年真题及答案(转载自百度文库)

第一步:读选项,混个眼熟
第二步:读文章标题
第三步:直接聚焦相应段落:找段落重要句

该文章的标题:
在这里插入图片描述
与人交谈的五种方法

在这里插入图片描述
红色是关键句,作者提到:
I know the feeling and here is my advice: just get it (想说的话) out. 读完回归众多选项,进行同义替换:

在这里插入图片描述
Just say it = Just get it out 同意替换,因此相比之下,A为正确答案

再比如:

在这里插入图片描述
Find the things which you and that person have in common 说白了就是找到你与交谈对象所具有的共同点!找到共同点后,两人才能建立connection,才能使得谈话更顺利!

聚焦选项,找与表达 “找共同点” 的同义替换:

在这里插入图片描述
再三斟酌,Find the “me too”s = have in common 能够形象地表达出共同点!因而,E成为正确答案。


四、翻译


翻译是可以说是,英语学科中,最难也是最重要的板块!这个板块中,我建议

前新东方名师,现跟谁学名师-教翻译的唐静老师

唐静老师所讲授的知识点特别他的《拆分与组合》,能够从根本上解决无法对句子进行长句断翻、短句补译、整理中英译法之差别等技巧。踏踏实实学翻译。

我建议:

1.跟唐静老师学视频课
2.利用学到的技巧,用在历年阅读真题上,精读文章中的句子!

五、作文


作文板块,我推荐王江涛老师的《考研英语高分写作》,基础不好的同学需要听王江涛老师的视频课,反复听!较好的有该书即可,并辅佐自己平时的总结!英语作文范文不在于多,而在于精,因此我建议范文处理方法:

  1. 针对历年真题的五篇不同话题/类型范文
  2. 《高分写作》老师所给预测五篇不同话题/类型
  3. 《高分写作》上每个板块的作文拓展词汇

最后,利用已有反复诵读的范文模板,尝试去做新题,输出学到的相应必备句型!模板的作用是在于用,不在于记!因而,要多用,否则考场上也无法很快地进入状态。

C/C++ 编程常见代码

1.加法器、累加器:(多实现 1+2+…+n 以及阶乘 n! 的功能)

一、求累加

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
int main(){

int i =0;
int res = 0;
int n;
cin >> n;

while(i<=n){
res += i;
i++;
}
//其中 res为最终结果 n表示加到多少 i表示每次加的数

cout << res <<endl;
return 0;
}

二、求某数阶乘

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19

int main()
{
int i = 1;
int sum = 1;
int n;
cin >> n;

while(i <=n){

sum *=i; // 1. sum = 1*1 =1
i++; // 2. i =2;
// 3. sum = 1*2=2 以此类推
}

cout << "其阶乘为:" << sum <<endl;

return 0;
}

2. 求两个数或数组中的最大值与最小值

int main(){

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
	int a, b,max;
cout << "请连续输入待比较的两个数,空格隔开:" <<endl;
cin >> a >> b;
max = (a>b) ? a : b; //使用双目运算符取得最大值
cout << max <<endl;

int arr[5] = {5, 2, 13, 23, 66};
int arr_max, arr_min;
arr_max = arr[0]; //默认第一位元素为最值
arr_min = arr[0];

for(int i =0; i <5; i++)
{
if(arr_max < arr[i])
{
arr_max = arr[i];
}else if(arr_min > arr[i]){ //往后遍历,若还有更大的则更新最值 否则最小值更新
arr_min = arr[i];
}
}
cout << arr_min << " " <<arr_max <<endl;

return 0;
}

3.冒泡排序,必须会默写

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
#define LEN 5
int main(){
int a[LEN] = {2, 13, 5, 55, 20};
for(int i=0; i<LEN; i++)
{
for(int j=0; j<LEN-i-1; j++){
//注意两个for循环的初始条件与终止条件 都从0k开始
if(a[j] > a[j+1]){
int t = a[j];
a[j] = a[j+1];
a[j+1] = t;
}
}
}
return 0;
}

4.简单的switch-case多分支条件语句

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
int main(){
int score;
cout << "请在0~100范围内输入你的分数(满分100分):" <<endl;
cout << " 60分以下不及格 60~70及格 70~80良好 80以上优秀 " <<endl;
cin >> score;

switch(score/10){
case 6 :
cout<<"及格"<<endl;
break;
case 7 :
cout<<"良好"<<endl;
break;
case 8 :
cout<<"优秀"<<endl;
break;
case 9 :
cout<<"优秀"<<endl;
break;
case 10 :
cout<<"满分"<<endl;
break;
default:
cout<<"不及格"<<endl;
break;
}
return 0;
}

5.求两个数的最大公约数、最小公倍数(不可含0) (谭浩强C语言例题)

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
int main(){
int x, y, r;
cout << "请输入待运算的两个数, 中间用空格隔开" <<endl;
cin >> x >> y;
int mul = x * y;

if(x > y) //将比如 8,2 与 2,8 的操作统一输出
{
r = x;
x = y;
y = r;
}

r = x % y; //直接判断两数是否可以整除

while(r){
x = y;
y = r;
r = x % y;
//辗转相除法
//直到余数不为0
//将余数作为除数 较小者作为被除数 继续求余判断
}
cout << "最大公约数:" << y << ",最小公倍数:" << mul / y <<endl;

return 0;
}

6.斐波那契数列递归

1
2
3
4
5
6
7
8
9
10
11
12
int fib(int n){
if(n == 1){

return 1;
}else if(n == 2){

return 1;
}else{

return fib(n-2) + fib(n-1);
}
}

1, 1, 2, 3, 5…以此类推

7.判断某数是否是素数 (谭浩强C语言例题)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23

int main()
{
int n, i;
bool isPrime = true;

cout << "输入一个正整数: ";
cin >> n;

for(i = 2; i <= n / 2; ++i)
{
if(n % i == 0) //只能被1 和 自身整除的数 才能是素数
{
isPrime = false;
break;
}
}
if (isPrime)
cout << "是素数";
else
cout << "不是素数";
return 0;
}

8.大写字母转化为小写字母

1
2
3
4
5
6
7
8
9
10
 
int main()
{

char a;
a = getchar();
printf("%c", a+32); // C或C语言中字符数据均以ASCII值存储 大写字母与小写字母相差32

return 0;
}

9.统计输入字符中单词的个数 (谭浩强C语言例题)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
#include<stdio.h>
#include<iostream>
#define N 30

using namespace std;
int main()
{
char b[N];
int word,count=0,i; //word代表是否是单词 1代表是 0代表不是单词 而是空格
//count 代表单词个数
puts("输入的字符长度要小于等于N"); // 例如-> hello world
gets(b);

for(i=0;b[i]!='\0';i++)
if(b[i]==' ') //若为空格则不是单词
word=0;
else if(word==0) //若是空格则遇到的新单词使得count加一
{
count++;
word=1;
}
printf("%d",count);
return 0;
}

10.求Sn=a+aa+aaa+…+aa…aaa(有n个a)之值,其中a是一个数字,为2。 例如,n=5时=2+22+222+2222+22222,n由键盘输入。 (谭浩强C语言例题)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
#include<iostream>
using namespace std;


int main()
{

int n,i,Sn =0,a=0;
cin >> n; //n代表循环次数

for(i=0; i<n; i++){
a = a*10 +2; // 0, 2, 22, 222
Sn += a; /0+2+22
}

cout << Sn;
return 0;
}

11.求Sn=1!+2!+3!+4!+5!+…+n!之值,其中n是一个数字(n不超过20) 注意使用int类型 当n为19时会溢出 (谭浩强C语言例题)

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
#include<iostream>
using namespace std;

long long fac(long long n){
long long i = 1;
long long sum = 1;
while(i <=n){
sum *=i; // 1. sum = 1*1 =1
i++; // 2. i =2;
// 3. sum = 1*2=2 以此类推
}
return sum;
}

int main()
{
long long n,sum=0,a = 0;
cin >> n;

for(long long i=n; i>0; i--){
sum += fac(i);
}
cout << sum << endl;
return 0;
}

12.求一个3×3矩阵对角线元素之和。 (谭浩强C语言例题)

在这里插入图片描述

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
#include<iostream>
using namespace std;

int main(){

int a[3][3];
for(int i=0; i<3; i++)
{
for(int j=0;j<3; j++){
cin >> a[i][j];
}
} //两个for循环输入二维数组

int sum1 = 0;
int sum2 = 0;
for(int i=0; i<3;i++)
{
sum1 += a[i][i]; //主对角线求和
}

int j=2;
for(int i=0;i<3;i++)
{

sum2 += a[i][j];
//副对角线求和 注意变量j定义在循环外 不然值不会发生改变
//j分别是2 1 0
j--;

}
cout << sum1 << " " << sum2;
return 0;
}

13.用选择法对10个整数从小到大排序。 (谭浩强C语言例题)

在这里插入图片描述

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
#include<iostream>
#define LEN 10
using namespace std;

void swap(int *a,int *b) //交换两个数 引用& 或者指针* 均可
{
int temp = *a;
*a = *b;
*b = temp;
}

void selection_sort(int arr[], int len)
{
int i,j;

for (i = 0 ; i < len - 1 ; i++)
{
int min = i; //默认选择最小值
for (j = i + 1; j < len; j++)
if (arr[j] < arr[min])
min = j;
swap(&arr[min], &arr[i]);
//调用数组元素时 元素前加引用
}
}

int main(){

int a[LEN];

for(int i=0; i<LEN; i++)
cin >> a[i];

selection_sort(a, LEN);

for(int i=0; i<LEN; i++){
cout << a[i] << endl;
}
return 0;
}

14.数组插入处理,对一个排好序的数组,按原来的规律插入某数

在这里插入图片描述

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
#include<iostream>
using namespace std;


int main(){
int a[5],x;
for(int i=0; i<5; i++){
scanf("%d" ,&a[i]); //输入数组
}

scanf("%d", &x); //输入待插入元素
for(int i=0; i<5; i++){
if(a[i]<x && a[i+1]>x) //满足条件模拟“插入” 并输入前后元素
cout << a[i] << " " <<x <<" ";
else
printf("%d ", a[i]); //否则正常输入
}
return 0;
}

15.写一个函数,使给定的一个二维数组(3×3)转置,即行列互换。 (谭浩强C语言例题)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
#include<iostream>
#define N 3
using namespace std;


int main(){
int a[N][N];
for(int i=0;i<N;i++){
for(int j=0;j<N;j++)
{
cin >> a[i][j];
}
}

for(int i=0;i<N;i++){
for(int j=0;j<N;j++)
{
cout << a[j][i] <<" "; //行列互换即可
}
cout << endl;
}
return 0;
}

16.自定义函数之字符串反转

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
#include<iostream>
#include<cstring>
#define N 100
using namespace std;


int main(){
char a[N];
cin >> a;
//遇tab、空格、回车都结束
//适合输入单个字符串且中间不含空格
//若需输入含空格的字符串 可用gets(str);
int len = strlen(a);

for(int i=len-1; i>=0; i--){
//注意字符数组的最后一个字符是 '\0'因而从倒数第二个开始
printf("%c", a[i]);
}

return 0;
}

17.写一函数,将两个字符串连接

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
#include<iostream>
#include<cstring>
#define N 100
using namespace std;


int main(){

char a[N], b[N];

cin >> a;
cin >> b;

int len_a = strlen(a);
int len_b = strlen(b);

for(int j = len_a,k=0; j < len_a + len_b; j++,k++ )
{
a[j] = b[k]; //后半部分赋新值即可
}
cout << a <<endl;

return 0;
}

18.写一函数,输入一个四位数字,要求输出这四个数字字符,但每两个数字间空格。如输入1990,应输出”1 9 9 0”。 (谭浩强C语言例题)

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
#include<iostream>
#include<cstring>
#include<stack>
#define N 100
using namespace std;


int main(){

//1990
int a;
stack<int> s; //利用栈stack从个位到最高位 进栈
cin >> a;

while(a>0){
s.push(a%10);
a /= 10;
}


while(!s.empty())
{
cout << s.top() << " "; //根据栈的FILO原则 出栈即可
s.pop();
}

return 0;
}

19.定义一个带参的宏,使两个参数的值互换,并写出程序,输入两个数作为使用宏时的实参。输出已交换后的两个值。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
#include<iostream>
#include<cmath>
#define exchange(a,b) t=a;a=b;b=t; //相当于整段代码替换

using namespace std;

int main(){
int a, b, t=0;
cin >> a >> b;

exchange(a,b);

cout << a << " " << b <<endl;
}

20.输入两个整数,求他们相除的余数。用带参的宏来实现,编程序。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
#include<iostream>
#include<cmath>
#define MOD(a,b,res) res = a % b; //相当于整段代码替换

using namespace std;

int main(){
int a, b, res=0;
cin >> a >> b;

MOD(a,b,res);

cout << res <<endl;
}

21.输入一行电报文字,将字母变成其下一字母(如’a’变成’b’……’z’变成’a’其它字符不变)。

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
#include<iostream>
#define N 100

using namespace std;

int main(){
char a[N];
gets(a); //输入字符串

for(int i=0; a[i] != '\0'; i++){
if(a[i] >= 'a' && a[i] < 'z'|| a[i] >= 'A' && a[i] < 'Z'){
a[i] += 1;
//C++与C一样 字符变量都由ASCII码整数存储
//因而 相应ASCII码自增1即可
}

if(a[i]=='z')
a[i] = 'a';

if(a[i]=='Z')
a[i] = 'A';
}
puts(a); //打印字符串
return 0;
}

22.现有N个学生的数据记录,每个记录包括学号、姓名、三科成绩。 编写一个函数input,用来输入一个学生的数据记录。 编写一个函数print,打印一个学生的数据记录。 在主函数调用这两个函数,读取N条记录输入,再按要求输出。 N<100

在这里插入图片描述

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
#include<iostream>
#define N 100

//class:
//私有属性:学号,姓名,三科成绩
//公有方法:void input(); void print();

using namespace std;
class Student{ //类名可以不大写,但是推荐大写 符合Java命名规范
public:
void input();
void print();

private:
string num;
//字符串类型 涉及到char 跟 int 的组合
//C++中的字符串是string类 Java中是String类
string name;
int Chinese;
int Math;
int English;
}; //记得有分号;

void Student::input(){ //记得域名符:: 表示实现Student类的方法
cin >> num >> name >> Chinese >> Math >> English; //加上域名符直接引用属性
}

void Student::print(){
cout << num << "," << name << "," << Chinese << "," << Math << "," << English <<endl;
}

int main(){
int n;
Student stu[N];

cin >> n;
for(int i=0; i<n; i++){
stu[i].input();
}

for(int i=0; i<n; i++){
stu[i].print();
}

return 0;
}

23.将一个字符串str的内容颠倒过来,并输出。str的长度不超过100个字符。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
#include<iostream>
#include<string>
#include<cstring>
#define N 100
using namespace std;

int main(){
char str[N];
gets(str);
int len = strlen(str);

for(int i=len-1; i>=0; i--){
//利用for循环颠倒该数组即可
//由于C++中最后一个字符是'\0' 因此从倒数第二个字符开始自减
cout << str[i];
}
}

24.解一元二次方程 (谭浩强C语言例题)

在这里插入图片描述

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
#include<iostream>
#include<cmath>
#include<string>
#include<cstring>
#define N 100
using namespace std;

int main(){
// a*x^2+b*x+c=0
int a, b, c;
double res1, res2;
cin >> a >> b >> c;

double delta = pow(b,2) - 4 * a * c;
if(delta == 0){
res1 = (-b + sqrt(delta) ) / 2 * a;
res2 = res1;
}else{
res1 = (-b + sqrt(delta) ) / 2 * a;
res2 = (-b - sqrt(delta) ) / 2 * a;
}

printf("%.2f %.2f", res1, res2);
return 0;
}

25.输入字符串 将组成字符的所有非英文字母的字符删除后输出

在这里插入图片描述

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
#include<iostream>
#include<vector>
#include<cmath>
#include<string>
#include<cstring>
#define N 100
using namespace std;

int main(){
//a ASCII是97
char str[N]; //定义所输入的字符数组
gets(str); //输入该数组的数据
int len = strlen(str);

vector<char> v; //定义vector模板类
for(int i=0; i<len; i++){
if(str[i] < 'A'|| str[i] >'Z'&& str[i] <'a' || str[i]>'z'){
}else{
//所输入数据是大小写字母时 存入动态数组vector中
v.push_back(str[i]);
}
}

for(int i=0; i < v.size(); i++){
cout << v[i];
}

return 0;
}

谭浩强第四版课后习题答案:

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
### 第二章:
2.4
#1、以参数形式交换两个数(记得参数加引用)
#include<iostream>
#include<stdio.h>
using namespace std;

void swap(int &a, int &b){
//什么时候用引用? 当需要将操作后的值 传递回去
int t = a;
a = b;
b = t;
}

int main(){
int num1, num2;
cin >> num1 >> num2;
swap(num1, num2);
cout << num1 << " " << num2;
return 0;
}

#2.依次输入5个值 要求输入其中的最大值
#include<iostream>
#include<stdio.h>
#define L 5
using namespace std;


int main(){
int a[L],max;
for(int i=0; i<L; i++){
cin >> a[i];
}

max = a[0];
for(int i=1; i<=5; i++){
if(max < a[i])
max = a[i];
}

cout << "Max is:" << max << endl;
return 0;
}

#3.有三个数a,b,c 要求输出最大值
#include<iostream>
#include<stdio.h>
#define L 5
using namespace std;


int main(){
int num1, num2, num3;
int max;
cin >> num1 >> num2 >> num3;
max = (num1 > num2)? num1 : num2; //第一个数与第二个数比较 结果是max
max = (max > num3)? max : num3; //max与第三个数比较 重新赋max的值
cout << max <<endl;
return 0;
}

#4.1+2+3+...+100
#include<iostream>
#include<stdio.h>
using namespace std;


int main(){
int i, sum=0;
while(i<=100){
sum += i;
i++;
}

cout << sum <<endl;

return 0;
}

#5.判断一个数是否同时被35整除
#include<iostream>
#include<stdio.h>
using namespace std;


int main(){
int num;
cin >> num;
if(num%3==0 && num%5 ==0){
printf("该数%d可以被3和5整除", num);
}else{
printf("不行");
}

return 0;
}

#6.输出100~200之间的素数
#include<iostream>
#include<stdio.h>
using namespace std;

bool fac(int x){
bool flag = true;
for(int i=2; i<x/2; i++){ //注意 对素数的判断 是需要判断2~n/2即可
if(x%i==0){
flag = false;
}
}
return flag;
}

int main(){
for(int i=100; i<=200; i++)
{
if(fac(i) == true)
{
printf("%d是素数\n", i);
}
}
return 0;
}

#7 求两个数的最大公约数
#include<iostream>
#include<stdio.h>
using namespace std;

void fun(int a, int b){ //传参进来a大于b
int c = a%b;
//辗转相除法 若余数为0 则小者为最大公约数

while(c != 0){ //如果余数不为0
a = b; //否则将余数作为除数
b = c; //小者作为被除数
c = a % b;
}
cout << b <<"是最大公约数" << endl;
}

void swap(int &a, int &b){
int t = a;
a = b;
b = t;
}

int main(){
int num1, num2;
cin >> num1 >> num2;
if(num1 < num2)
swap(num1, num2); //对大小相反做处理 交换即可
fun(num1, num2);
return 0;
}

#8. 求一元二次方程的根
#include<iostream>
#include<cmath>
#include<stdio.h>
using namespace std;


int main(){
//ax^2 + bx + c
double a, b, c;
cin >> a >> b >> c;
double delt = pow(b,2) - 4 * a * c;
double x1 = (-b+sqrt(delt))/(2*a);
double x2 = (-b-sqrt(delt))/(2*a);

if(delt > 0){
cout << "实根分别为:" << x1 << " " << x2 <<endl;
}else{
if(delt == 0){
cout << "实根为:" << x1 << endl;
}else{
cout << "无实根" << endl;
}
}

return 0;
}

第三章

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


第三章:
#3-5

#include<iostream>
#include<stdio.h>
using namespace std;

int main(){

int a,b;
float x;
double y;
char c1, c2;
printf("input the Integer a,b:\n");
scanf("%d %d",&a, &b);

printf("input the Float x:\n");
scanf("%f",&x);

printf("input the Double y:\n");
scanf("%lf",&y);

printf("input the char c1:\n");
c1 = getchar();

printf("input the char c2:\n");
c2 = getchar();

printf("%d,%d,%.2f,%.2lf,%c,%c",a,b,x,y,c1,c2);
return 0;
}

#3.6加密 将China译成密码 利用char字符在计算机中存储ASCII码值 每个字符相加四个单位即可
#include<iostream>
#include<stdio.h>
using namespace std;

int main(){
char c1,c2,c3,c4,c5;
c1 = 'C';
c2 = 'h';
c3 = 'i';
c4 = 'n';
c5 = 'a';

c1+=4;
c2+=4;
c3+=4;
c4+=4;
c5+=4;

putchar(c1);
putchar(c2);
putchar(c3);
putchar(c4);
putchar(c5);

printf("\n");

printf("%c%c%c%c%c",c1,c2,c3,c4,c5);

return 0;
}

第五章

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
第五章:
5.3 求最大公约数与最小公倍数

5.3.1:最大公约数:
#include<stdio.h>
#include<iostream>
#include<stack>
#define N 100
using namespace std;

int main(){
//求a b两个数字的最大公约数 (辗转相除法)
int a, b, res = 0;
cin >> a >> b;
if(a < b) //默认a>b
{
int t = a;
a = b;
b = t;
}

if(a % b == 0){ //如果a是b的倍数 那么最大公因数就是b
res = b;
}else{
int c = a % b; //否则先取余 余数在else语句中肯定是不为0的
while(c != 0){ //若若满足不为0 则较小数作为a 余数作为b c重新被a b取余
a = b;
b = c;
c = a % b;
}

res = b;
}
cout << res;
return 0;
}

5.3.2:最小公倍数:
#include<stdio.h>
#include<iostream>
#include<stack>
#define N 100
using namespace std;

int main(){
//求a b两个数字的最小公倍数
int a,b,res=0;

cin >> a >> b;
if(a < b){ //默认a大于b
int t = a;
a = b;
b = t;
}

if(a % b == 0){ //如果a是b的倍数 那么最小公倍数就是a
res = a;
}else{
int temp=b;
while(temp<=a*b){ //直到temp变成a*b
if(temp%a==0&&temp%b==0){ //如果从较小数开始 一直自增 如果能同时取余两个数 那么就是公倍数
res = temp;
break;
}
temp++;
}
}

cout << res <<endl;
return 0;
}

5.8 输出所有水仙花数(三位数,且各数的立方和等于该数本身):
#include<stdio.h>
#include<vector>
#include<cmath>
#include<iostream>
#include<stack>
#define N 100
using namespace std;
bool isNum(int num){
int sum = 0;
vector<int> v(1, num);
vector<int>::iterator it;
bool flag = false;

while(num){
v.push_back(num%10);
num /= 10;
}

for(it=v.begin()+1; it != v.end(); it++){
sum += (pow(*it, 3));
}


if(sum == v[0]){
flag = true;
}

return flag;
}

int main(){
//求所有的水仙花
int num;
for(int i =100; i<1000; i++){
if(isNum(i)){
cout << i << " ";
}
}

return 0;
}

5.91000之内的所有完数
#include<stdio.h>
#include<vector>
#include<cmath>
#include<iostream>
#include<stack>
#define N 100
using namespace std;

void getNum(int num){
int sum=0;
vector<int> v(1, num);
vector<int>::iterator it;

for(int i=1; i<num; i++){ //千万注意 取余的两边绝对!绝对不能为0 因此i不能是0
if(num%i==0)
v.push_back(i);
}

for(it=v.begin()+1; it!=v.end(); it++){
sum += (*it);
}

if(sum == v[0]){
cout << sum << "是完数" << endl;
}
v.clear();
}

int main(){
//求完数 即一个数等于它所有的因子之和
int num,end = 1000;
while(num++ < end){
getNum(num);
}
return 0;
}

5.10:求 2/1 + 3/2 + 5/3 +... 数列的前20项和

#include<stdio.h>
#include<vector>
#include<cmath>
#include<iostream>
#include<stack>
#define N 100
using namespace std;


int main(){
double up=2, down=1,res = 0; //up代表分母 down代表分子
int i=0;
while(i++<20){
res += (up/down);
up = up + down;
down = up - down; //注意 这里不能用down = up 因为up 已经是 up+down
//而应该是新的up减去之前的down
}

cout << res;
return 0;
}

5.11: 一个球从100M高度落下 每次落地反弹回原高度的一般 再落下...求第10次 共经过多少米 反弹多高?
#include <stdio.h>
main()
{
float height=100.0,sum_height=100;
int i;
for(i=1;i<10;i++) {
height=height/2;
sum_height+=height*2;
}
printf("%fm\n",sum_height);
printf("%fm\n",height);
return 0;
}

第六章:

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
第六章:
例题:输入字符串 从中打印出单词的个数

#include <stdio.h>
#include<iostream>
#include<vector>
#include<stack>
#define N 100
using namespace std;


main()
{
char str[N];
int num,word=0;
gets(str);

for(int i=0; str[i]!='\0'; i++){
if(str[i] == ' '){ //如果一开始就是空格 那么不是单词
word = 0;
}else if(word==0){ //空格之后 认为是单词 记为遇到1个
word = 1;
num++;
}
}

cout << num <<endl;
return 0;
}

6.5:逆序存放升序的数组 比如处理前:1 2 3 4 5 存放后为:5 4 3 2 1
#include <stdio.h>
#include<iostream>
#include<vector>
#include<stack>
#define N 100
using namespace std;


main()
{
int arr[N],len;
stack<int> s;

cin >> len;
for(int i=0; i<len; i++)
{
cin >> arr[i];
s.push(arr[i]); //利用栈的FILO原理 从头到尾将元素进行入栈
}

cout << "处理前的数组元素分别为:" <<endl;
for(int i =0; i<len; i++)
cout << arr[i] << " ";

cout << endl;

for(int i=0; i<len; i++){
arr[i] = s.top();
s.pop();
}

cout << "处理后的数组元素分别为:" <<endl;
for(int i =0; i<len; i++)
cout << arr[i] << " ";

return 0;
}
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
6.9
有若干个数字在有序数组中 此时要求实现折半查找方式来查找某个元素
并给出它的位置 若找不到该数 则输出 无此数
#include <stdio.h>
#include<iostream>
#include<vector>
#include<stack>
#define N 100
using namespace std;


int main()
{
int a[6] = {1, 4, 6, 32, 58, 66};
int left = 0;
int right = 5; //注意是最后一个元素 即 长度-1
int mid,num;
cout << "输入欲查找的数字:" <<endl;
cin >> num;
while(left <= right){ //注意条件
mid = (left + right) / 2;
if(a[mid] == num){
cout << "已找到,是第" << mid+1 << "个元素" <<endl;
break;
}else if(a[mid] < num){
left = mid + 1;
}else{
right = mid - 1;
}
}

if(left > right){
cout << "无此数" <<endl;
}
return 0;
}

统计各字符
#include <stdio.h>
#include<iostream>
#include<vector>
#include<stack>
#define N 100
using namespace std;


int main()
{
char str[2][10];
for(int i =0; i<2; i++)
gets(str[i]); //for循环每次输入该行

cout << endl;

//统计大写字母 小写字母 数字 空格以及其他字符

int num=0, U_char=0, L_char=0, space=0, oth=0;

for(int i =0; i<2; i++) {
for(int j=0; j<10; j++){
char ch= str[i][j];
if(ch >= '0' && ch <= '9' ){
num++;
}else if(ch >= 'A' && ch <= 'Z'){
U_char++;
}else if(ch >= 'a' && ch <= 'z'){
L_char++;
}else if(ch == ' '){
space++;
}else{
oth++;
}
}
}

cout << "数字:" << num<<endl;
cout << "大写字母:" << U_char <<endl;
cout << "小写字母:" << L_char << endl;
cout << "空格:" <<space <<endl;
cout << "其他:" << oth <<endl;

return 0;
}

6.14
比较两个字符串 其中返回正数 该正数表示相差的总值
#include <stdio.h>
#include<iostream>
#include<cstring>
#include<cmath>
#include<vector>
#include<stack>
#define N 100
using namespace std;


int main()
{
//两个字符串的比较 返回总相差的ASCII码值
char c1[N], c2[N];
int len1, len2;
int sum=0;
cout << "请输入字符串一:" <<endl;
gets(c1);
len1 = strlen(c1);

cout << "请输入字符串二:" <<endl;
gets(c2);
len2 = strlen(c2);
int len = (len1>len2)? len1: len2;
for(int i=0; i<len; i++){
sum += abs(c1[i]-c2[i]);
}

cout << "两者相差:" << sum <<endl;
return 0;
}

6.15 将字符数组a2的所有字符都复制到a1中去 其中包括a2的结束字符'\0'
#include <stdio.h>
#include<iostream>
#include<cstring>
#include<cmath>
#include<vector>
#include<stack>
#define N 100
using namespace std;


int main()
{
//两个字符串的比较 返回总相差的ASCII码值
char c1[N], c2[N]={'v','i','n','c','\0'};
int len1, len2;
cout << "请输入字符串一:" <<endl;
gets(c1);
len1 = strlen(c1);

cout << "请输入字符串二:" <<endl;

len2 = strlen(c2)+1;

for(int k = len1,i=0; k<len1+len2; k++,i++){
c1[k] = c2[i];
}

for(int k = 0; k<len1+len2; k++){
printf("%c它的ASCII值为%d\n", c1[k],c1[k]);
}

return 0;
}

第七章:

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

7.10:写一个函数,输入一行字符,将最长的单词输出:
【转】:https://blog.csdn.net/navicheung/article/details/77990479

#include<stdio.h>
#include<iostream>
#include<cstring>
#include<string>
#include<cmath>
#include<vector>
#include<stack>
#define N 100
using namespace std;

//最长单词函数
void getLongWord(char str[])
{
int max_length=0, len=0;
char temp[N], res[N];
int n = strlen(str);

for (int i=0; i<=n; i++){

//如果字符是单词的一部分 加入到temp数组
if ((str[i]>='a'&&str[i]<='z')||(str[i]>='A'&&str[i]<='Z'))
temp[len++]=str[i];
else{
//若不是单词 那么temp数组不再增添元素 而是结束
temp[len]='\0';

//如果每次长度有更长的 更新 且记得len重新赋值为0 以下一次判断
//最终的结果存入ma数组中 关键语句
len>max_length ? max_length=len, strcpy(res, temp), len=0 : len=0;
}
}

printf("最长的单词是: ");
puts(res);
}

int main()
{
char str[N];
printf("请输入字符串:\n "); //输入一行字符
gets(str);

getLongWord(str); //调用最长单词函数

return 0;
}

7.11 利用起泡法对输入的n个字符进行升序排序:
#include<stdio.h>
#include<iostream>
#include<cstring>
#include<string>
#include<cmath>
#include<vector>
#include<stack>
#define N 100
using namespace std;

void swap(char &a, char &b){
char t = a;
a = b;
b = t;
}

int main()
{
char str[N];
int length;

cout << "你要输入几个字符:" <<endl;
cin >> length;

cout << "依次输入这些字符:" <<endl;
for(int i=0; i<length; i++){
cin >> str[i];
}

for(int i=0; i<length; i++){
for(int j=0; j<length-i-1; j++){
if(str[j] > str[j+1]){
swap(str[j], str[j+1]);
}
}
}

cout << "起泡法排序结果:" <<endl;
for(int i=0; i<length; i++)
cout << str[i] << " ";
return 0;
}

7.16 输入一个十六进制数字(字符串的形式),输出相应的十进制数字:
#include<stdio.h>
#include<iostream>
#include<cstring>
#include<string>
#include<cmath>
#include<vector>
#include<stack>
#define N 100
using namespace std;

//十六进制数转换为十进制数
//相应的位置 按权展开即可
//A2 = A*10^1 + 2*10^0
int fun(char str[]){

int n = strlen(str); //n代表字符串的长度 即代表十六进制数是n位数
int sum =0;

for(int i=n-1,j=0; i>=0; i--){
int temp = 0;
if(str[i]=='A'){
temp = 10;
}else if(str[i]=='B'){
temp = 11;
}else if(str[i]=='C'){
temp = 12;
}else if(str[i]=='D'){
temp = 13;
}else if(str[i]=='E'){
temp = 14;
}else if(str[i]=='F'){
temp = 15;
}else{
temp = str[i] - '0';
}
sum += (temp * pow(16, j++));
}
return sum;
}

int main()
{
char str[N];
gets(str);

cout << "十进制数是:" <<endl;
cout << fun(str) <<endl;

return 0;
}

7.17 递归法 将一个整数转换为字符串
#include<stdio.h>
#include<iostream>
#include<cstring>
#include<string>
#include<cmath>
#include<vector>
#include<stack>
#define N 100
using namespace std;

//将一个整数 转换成字符串

void fun(int n){
char ch; //每次输出的字符

//1.递归的第一步 首先想好边界情况 这里每次i位数每次取i-1 直到结果为0
if(n==0){
return;
}else{
//2.否则 执行每一次的操作具体的行为
//注意这里fun一直到边界才输出!因此结果是12(假如n=12)
//如果fun放在末尾 那么会先输出数字 因而结果会是21
fun(n/10);
printf("%c", (n%10) + '0');
}
}

int main()
{
int num =0;
cin >> num;

fun(num);

return 0;
}

6.18:给出年、月、日 计算是该年的第几天

#include<stdio.h>
#include<iostream>
#include<cstring>
#include<string>
#include<cmath>
#include<vector>
#include<stack>
#define N 100
using namespace std;

bool isLeapYear(int year){
bool flag = false;
if( year%400==0 || (year%4==0&&year%100!=0) ){
//1.被400整除的年份是闰年
//2.被4整除同时不能被100所整除的年份是闰年
flag = true;
}
return flag;
}

//输入某年某月某日 判断这是该年中的第几天
void fun(int year, int month, int day){
int months[12] = {31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31}; //非闰年的各月份天数数组
int days_sum = 0,i=0;

if(month<2){ //如果没到2月 则不用计算是不是闰年
days_sum = day;
cout << "该日期是第" << days_sum << "天" <<endl;
}else{
if(isLeapYear(year)){
months[1] = 29; //闰年2月有29天
}

while(i<month-1){ //计算该月之前有多少天
days_sum += months[i];
i++;
}
//然后该月第几天加上去
cout << "该日期是第" << days_sum+day << "天" <<endl;
}

}

int main()
{
int year, month, day;
cout << "输入年份:" <<endl;
cin >> year;

cout << "输入月:" <<endl;
cin >> month;

cout << "输入日:" << endl;
cin >> day;

//可以添加判断日期是否合法的函数... 现假设合法 正确输入格式

fun(year, month, day);
return 0;
}


C/C++力扣LeetCode转载

27.原地移出某数后的数组

给你一个数组 nums 和一个值 val,你需要 原地 移除所有数值等于 val 的元素并返回移除后数组的新长度。不要使用额外的数组空间,你必须仅使用 O(1) 额外空间并 原地 修改输入数组。元素的顺序可以改变。你不需要考虑数组中超出新长度后面的元素。

说明:
为什么返回数值是整数,但输出的答案是数组呢?
请注意,输入数组是以「引用」方式传递的,这意味着在函数里修改输入数组对于调用者是可见的。
你可以想象内部操作如下:

// nums 是以“引用”方式传递的。也就是说,不对实参作任何拷贝
int len = removeElement(nums, val);

// 在函数里修改输入数组对于调用者是可见的。
// 根据你的函数返回的长度, 它会打印出数组中 该长度范围内 的所有元素。
for (int i = 0; i < len; i++) {
print(nums[i]);
}

示例 1:

输入:nums = [3,2,2,3], val = 3
输出:2, nums = [2,2]
解释:函数应该返回新的长度 2, 并且 nums 中的前两个元素均为 2。你不需要考虑数组中超出新长度后面的元素。例如,函数返回的新长度为 2 ,而 nums = [2,2,3,3] 或 nums = [2,2,0,0],也会被视作正确答案。
示例 2:

输入:nums = [0,1,2,2,3,0,4,2], val = 2
输出:5, nums = [0,1,4,0,3]
解释:函数应该返回新的长度 5, 并且 nums 中的前五个元素为 0, 1, 3, 0, 4。注意这五个元素可为任意顺序。你不需要考虑数组中超出新长度后面的元素。

来源:力扣(LeetCode)
链接:https://leetcode-cn.com/problems/remove-element
著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。

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
class Solution {
public:
int removeElement(vector<int>& nums, int val) {
if(nums.size() == 0) return 0;
//一个指针指向头 一个指向尾部
int i = 0, index = nums.size()-1;
while(i <= index)
{
//如果当前是要删除的值
if(nums[i] == val)
{
//将该数字与最后一个数字交换
//同时数组缩减
int temp = nums[index];
nums[index] = nums[i];
nums[i] = temp;
--index;
}
//如果不是要删除的值 继续往后推进
else
++i;
}
return i;
}

};

作者:Xiaohu9527
链接:https://leetcode-cn.com/problems/remove-element/solution/cyi-ci-li-bian-bu-xu-yao-bao-li-gan-jue-82cz7/
来源:力扣(LeetCode)
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。

58.返回最后一个单词的长度

给你一个字符串 s,由若干单词组成,单词之间用空格隔开。返回字符串中最后一个单词的长度。如果不存在最后一个单词,请返回 0(注意本题最后 可能出现连续的空格)单词 是指仅由字母组成、不包含任何空格字符的最大子字符串。

示例 1:

输入:s = “Hello World”
输出:5
示例 2:

输入:s = “ “
输出:0

来源:力扣(LeetCode)
链接:https://leetcode-cn.com/problems/length-of-last-word
著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。

1
2
3
4
5
6
7
8
9
10
11
int lengthOfLastWord(string s) {
int count = 0, end = s.size()-1;
//直到最后一个变成第一个
//未遇到第一个字母前 若有连续的空格 直接跳过
while(end >= 0 && s[end] == ' ')
--end;
//如果没有遇到最后一个字母前的空格 就count++ 且每次指针 end--
while(end >= 0 && s[end--] != ' ')
++count ;
return count;
}

动态规划实现斐波那契数列

假设你正在爬楼梯。需要 n 阶你才能到达楼顶。每次你可以爬 1 或 2 个台阶。你有多少种不同的方法可以爬到楼顶呢?注意:给定 n 是一个正整数。

示例 1:
输入: 2
输出: 2
解释: 有两种方法可以爬到楼顶。

  1. 1 阶 + 1 阶
  2. 2 阶

示例 2:
输入: 3
输出: 3
解释: 有三种方法可以爬到楼顶。

  1. 1 阶 + 1 阶 + 1 阶
  2. 1 阶 + 2 阶
  3. 2 阶 + 1 阶

来源:力扣(LeetCode)
链接:https://leetcode-cn.com/problems/climbing-stairs
著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
//一定看懂本题的动态规划
//利用dp[i]将可能用到的值存起来 return dp[n]
int climbStairs(int n) {
vector<int> dp(n+3, 0); //元素个数为n+3 默认为0
dp[0] = 0;
dp[1] = 1;
dp[2] = 2;

//用数组把值存储起来 如果下次需要 直接调用相应的数组值即可
for(int i=3; i<=n; i++){
dp[i] = dp[i-1] + dp[i-2];
}
return dp[n];
}

合并有序数组使其有序

给你两个有序整数数组 nums1 和 nums2,请你将 nums2 合并到 nums1 中,使 nums1 成为一个有序数组。 (本来都有序,想要合并之后仍有序)初始化 nums1 和 nums2 的元素数量分别为 m 和 n 。你可以假设 nums1 的空间大小等于 m + n,这样它就有足够的空间保存来自 nums2 的元素。

示例 1:
输入:nums1 = [1,2,3,0,0,0], m = 3, nums2 = [2,5,6], n = 3
输出:[1,2,2,3,5,6]

示例 2:
输入:nums1 = [1], m = 1, nums2 = [], n = 0
输出:[1]

来源:力扣(LeetCode)
链接:https://leetcode-cn.com/problems/merge-sorted-array
著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。

1
2
3
4
5
6
7
8
9
10
11
12
class Solution {
public:
void merge(vector<int>& nums1, int m, vector<int>& nums2, int n) {
//从将nums2的全部内容 排在nums1的数组后面
for(int k=m,j=0; k<m+n; k++,j++){
nums1[k] = nums2[j];
}
//整体对nums1第一个元素 以及加进来之后的最后一个元素进行排序即可 注意排序的长度是容纳n1 n2的长度之和
sort(nums1.begin(), nums1.begin()+(m+n));

}
};

找到值的索引 或者理应插入的位置

给定一个排序数组和一个目标值,在数组中找到目标值,并返回其索引如果目标值不存在于数组中,返回它将会被按顺序插入的位置。你可以假设数组中无重复元素。

示例 1:

输入: [1,3,5,6], 5
输出: 2
示例 2:

输入: [1,3,5,6], 2
输出: 1
示例 3:

输入: [1,3,5,6], 7
输出: 4
示例 4:

输入: [1,3,5,6], 0
输出: 0

来源:力扣(LeetCode)
链接:https://leetcode-cn.com/problems/search-insert-position
著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。

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
class Solution {
public:
int searchInsert(vector<int>& nums, int target) {
int pos = 0;
int end = nums.size();

//处理特殊情况 当小于第一个或者大于最后一个时
if(target < nums[0]){
return pos;
}

if(target > nums[end-1]){
pos = end;
return pos;
}


//如果中间有 那么返回该位置
for(int i=0; i<end; i++){
if(target == nums[i]){
pos = i;
return pos;
}
}

//如果下一个比它大 则返回下一个位置
for(int i=0; i<end; i++){
if(target >nums[i] && target < nums[i+1]){
pos = i+1;
return pos;
}
}
return pos;
}
};

121. 买卖股票的最佳时机

给定一个数组 prices ,它的第 i 个元素 prices[i] 表示一支给定股票第 i 天的价格。
你只能选择 某一天 买入这只股票,并选择在 未来的某一个不同的日子 卖出该股票。设计一个算法来计算你所能获取的最大利润
返回你可以从这笔交易中获取的最大利润。如果你不能获取任何利润,返回 0 。

示例 1:
输入:[7,1,5,3,6,4]
输出:5
解释:在第 2 天(股票价格 = 1)的时候买入,在第 5 天(股票价格 = 6)的时候卖出,最大利润 = 6-1 = 5 。
注意利润不能是 7-1 = 6, 因为卖出价格需要大于买入价格;同时,你不能在买入前卖出股票。

示例 2:
输入:prices = [7,6,4,3,1]
输出:0
解释:在这种情况下, 没有交易完成, 所以最大利润为 0。

来源:力扣(LeetCode)
链接:https://leetcode-cn.com/problems/best-time-to-buy-and-sell-stock
著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。

1
2
3
4
5
6
7
8
9
10
11
class Solution {
public:
int maxProfit(vector<int>& prices) {
int profit=0, minValue=prices[0]; //假设第一个是最小值
for(int i=1; i<prices.size(); i++){ //从第二个到最后一个开始
minValue = min(minValue, prices[i]); //每次比较minValue与当前值的最小值
profit = max(profit, prices[i]-minValue); //利润就是当前值减去最小值的最大差值
}
return profit;
}
};

202. 快乐数

编写一个算法来判断一个数 n 是不是快乐数。
「快乐数」定义为:
对于一个正整数,每一次将该数替换为它每个位置上的数字的平方和。然后重复这个过程直到这个数变为 1,也可能是 无限循环 但始终变不到 1。
如果 可以变为  1,那么这个数就是快乐数。
如果 n 是快乐数就返回 true ;不是,则返回 false 。

示例 1:
输入:19
输出:true
解释:
12 + 92 = 82
82 + 22 = 68
62 + 82 = 100
12 + 02 + 02 = 1

示例 2:
输入:n = 2
输出:false

来源:力扣(LeetCode)
链接:https://leetcode-cn.com/problems/happy-number
著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。

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
class Solution {
public:
//拿到相应的各数之和函数
int getNum(int n){
int sum=0;
while(n){
sum += (pow(n%10, 2));
n /= 10;
}
return sum;
}

bool isHappy(int n) {
set<int> s;
//定义一个集合 因为如果结果不为1 相加一定有重复的数字

while(1){ //一直循环

int sum = getNum(n);
//每次将结果放入集合之前 先判断集合是否已经存在该元素

//如果已经出现了 说明结果肯定不会等于1
if(s.count(sum) == 1){
return false;
}

//如果没有重复 则加入
s.insert(sum);

//如果结果等于1 则返回true
if(sum == 1){
return true;
}
//对每一次得到的sum重复计算!
n = sum;
}
}
};

136. 只出现一次的数字

给定一个非空整数数组,除了某个元素只出现一次以外,其余每个元素均出现两次。找出那个只出现了一次的元素。

示例 1:
输入: [2,2,1]
输出: 1

示例 2:
输入: [4,1,2,1,2]
输出: 4

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
class Solution {
public:
int singleNumber(vector<int>& nums) {
set<int> s;
int res = 0;
for(int i=0; i<nums.size(); i++){
if(s.count(nums[i]) == 1){ //如果集合中有这个元素 那么删除它
s.erase(nums[i]);
}else{//如果集合中没有这个元素 就添加进去
s.insert(nums[i]);
}
}
set<int>::iterator it;
for(it=s.begin();it != s.end(); it++){
res = *it;//最后剩余的元素 一定是不重复的元素
}
return res;
}
};

204. 计数质数

统计所有小于非负整数 n 的质数的数量。

示例 1:
输入:n = 10
输出:4
解释:小于 10 的质数一共有 4 个, 它们是 2, 3, 5, 7 。

示例 2:
输入:n = 0
输出:0

示例 3:
输入:n = 1
输出:0

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
class Solution {
public:
bool isPrime(int x) {
//在0~根号x的范围内 即可判断是否是质数
for (int i = 2; i * i <= x; ++i) {
if (x % i == 0) {
return false;
}
}
return true;
}

//在C++中 true的数字代表1 多少个true相加
//就代表有多少个质数 从2~n-1判断即可
int countPrimes(int n) {
int ans = 0;
for (int i = 2; i < n; ++i) {
ans += isPrime(i);
}
return ans;
}
};

217. 存在重复元素

给定一个整数数组,判断是否存在重复元素。

如果存在一值在数组中出现至少两次,函数返回 true 。如果数组中每个元素都不相同,则返回 false 。

示例 1:
输入: [1,2,3,1]
输出: true

示例 2:
输入: [1,2,3,4]
输出: false

示例 3:
输入: [1,1,1,3,3,4,3,2,4,2]
输出: true

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
class Solution {
public:
bool containsDuplicate(vector<int>& nums) {
set<int> s;

for(int i=0; i<nums.size(); i++){

//如果集合中存在重复元素 直接return真
if(s.count(nums[i]) == 1){
return true;
}

//否则持续向集合中 添加数组中的元素
s.insert(nums[i]);
}
return false;
}
};

258. 各位相加

给定一个非负整数 num,反复将各个位上的数字相加,直到结果为一位数。

示例:
输入: 38
输出: 2
解释: 各位相加的过程为:3 + 8 = 11, 1 + 1 = 2。 由于 2 是一位数,所以返回 2。

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
class Solution {
public:
//计算各数之和的方法
int getNum(int num){
int res = 0;
while(num){
res += num%10;
num /= 10;
}
return res;
}

int addDigits(int num) {
int res = 0;
//不到跳出循环的条件不罢休
while(1){
//算出num的各数之和
res = getNum(num);
//直到算到个数之和小于10
if(res<10){
return res;
}
//下一次计算新结果的个数之和
num = res;
}
}
};

28.实现 strStr()

给定一个 haystack 字符串和一个 needle 字符串,在 haystack 字符串中找出 needle 字符串出现的第一个位置 (从0开始)。如果不存在,则返回  -1。

示例 1:
输入: haystack = “hello”, needle = “ll”
输出: 2

示例 2:
输入: haystack = “aaaaa”, needle = “bba”
输出: -1

当 needle 是空字符串时,我们应当返回什么值呢?这是一个在面试中很好的问题。
对于本题而言,当 needle 是空字符串时我们应当返回 0 。这与C语言的 strstr() 以及 Java的 indexOf() 定义相符。

来源:力扣(LeetCode)
链接:https://leetcode-cn.com/problems/implement-strstr
著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
class Solution {
public:
int strStr(string haystack, string needle) {
int pos = 0;
//如果是空字符串 返回0
if(needle == " "){
return pos;
}else{
//如果不为空 则找到对应的位置
pos = haystack.find(needle);
//如果找得到 返回位置
if( pos != string::npos){
return pos;
}
}
//如果找不到 就返回-1
return -1;
}
};

83. 删除排序链表中的重复元素

给定一个排序链表,删除所有重复的元素,使得每个元素只出现一次。

示例 1:
输入: 1->1->2
输出: 1->2

示例 2:
输入: 1->1->2->3->3
输出: 1->2->3

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
/**
* Definition for singly-linked list.
* struct ListNode {
* int val;
* ListNode *next;
* ListNode() : val(0), next(nullptr) {}
* ListNode(int x) : val(x), next(nullptr) {}
* ListNode(int x, ListNode *next) : val(x), next(next) {}
* };
*/
class Solution {
public:
ListNode* deleteDuplicates(ListNode* head) {
ListNode* cur = head;
while(cur != NULL && cur->next != NULL){
if(cur->val == cur->next->val){
cur->next = cur->next->next;
}else{
cur = cur->next;
}
}
return head;
}
};

344. 反转字符串

编写一个函数,其作用是将输入的字符串反转过来。输入字符串以字符数组 char[] 的形式给出。

不要给另外的数组分配额外的空间,你必须原地修改输入数组、使用 O(1) 的额外空间解决这一问题。

你可以假设数组中的所有字符都是 ASCII 码表中的可打印字符。

示例 1:
输入:[“h”,”e”,”l”,”l”,”o”]
输出:[“o”,”l”,”l”,”e”,”h”]

示例 2:
输入:[“H”,”a”,”n”,”n”,”a”,”h”]
输出:[“h”,”a”,”n”,”n”,”a”,”H”]

来源:力扣(LeetCode)
链接:https://leetcode-cn.com/problems/reverse-string
著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
class Solution {
public:
void reverseString(vector<char>& s) {
//给俩指针 一个指针指向第一个元素
//再给一个指针给最后一个元素
int i = 0;
int end = s.size()-1;
//直到俩指针相遇
while(i<=end){
//交换首尾元素
char temp = s[i];
s[i] = s[end];
s[end] = temp;

i++;
end--;
}
}
};

383. 赎金信

给定一个赎金信 (ransom) 字符串和一个杂志(magazine)字符串,判断第一个字符串 ransom 能不能由第二个字符串 magazines 里面的字符构成。
如果可以构成,返回 true ;否则返回 false。
(题目说明:为了不暴露赎金信字迹,要从杂志上搜索各个需要的字母,组成单词来表达意思。杂志字符串中的每个字符只能在赎金信字符串中使用一次。)

示例 1:
输入:ransomNote = “a”, magazine = “b”
输出:false

示例 2:
输入:ransomNote = “aa”, magazine = “ab”
输出:false

示例 3:
输入:ransomNote = “aa”, magazine = “aab”
输出:true

来源:力扣(LeetCode)
链接:https://leetcode-cn.com/problems/ransom-note
著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。

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
class Solution {
public:
bool canConstruct(string ransomNote, string magazine) {
int count = 0; //count用来标记r串中 可以找到的个数
int r_i = 0;
int r_len = ransomNote.size();
int m_end = magazine.size();

//从ran字符串中 一个一个判断
while(r_i < r_len){
int pos = magazine.find(ransomNote[r_i]);
if( pos != string::npos){
count++;

//从mag中原地删除字符
int temp = magazine[pos];
magazine[pos] = magazine[m_end-1];
magazine[m_end-1] = temp;

//删除最后一个字符
magazine.erase(m_end-1);
}
r_i++;
}
//如果都可以找到 就代表true
if(count == ransomNote.size()){
return true;
}
return false;
}
};

387. 字符串中的第一个唯一字符

给定一个字符串,找到它的第一个不重复的字符,并返回它的索引。如果不存在,则返回 -1。

示例:
s = “leetcode”
返回 0

s = “loveleetcode”
返回 2

提示:你可以假定该字符串只包含小写字母。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
class Solution {
public:
int firstUniqChar(string s) {

unordered_map<char, int> frequency;

//将字符串中的每个字符 遇到一个自增
for (char ch: s) {
++frequency[ch];
}

//从头到尾 输出第一个频度为1的
for (int i = 0; i < s.size(); ++i) {
if (frequency[s[i]] == 1) {
return i;
}
}
return -1;
}
};

268. 丢失的数字

给定一个包含 [0, n] 中 n 个数的数组 nums ,找出 [0, n] 这个范围内没有出现在数组中的那个数。

示例 1:
输入:nums = [3,0,1]
输出:2
解释:n = 3,因为有 3 个数字,所以所有的数字都在范围 [0,3] 内。2 是丢失的数字,因为它没有出现在 nums 中。

示例 2:
输入:nums = [0,1]
输出:2
解释:n = 2,因为有 2 个数字,所以所有的数字都在范围 [0,2] 内。2 是丢失的数字,因为它没有出现在 nums 中。

示例 3:
输入:nums = [9,6,4,2,3,5,7,0,1]
输出:8
解释:n = 9,因为有 9 个数字,所以所有的数字都在范围 [0,9] 内。8 是丢失的数字,因为它没有出现在 nums 中。

示例 4:
输入:nums = [0]
输出:1
解释:n = 1,因为有 1 个数字,所以所有的数字都在范围 [0,1] 内。1 是丢失的数字,因为它没有出现在 nums 中。

提示:
n == nums.length
1 <= n <= 104
0 <= nums[i] <= n
nums 中的所有数字都 独一无二

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
class Solution {
public:
int missingNumber(vector<int>& nums) {
//首先从小到大进行排序
sort(nums.begin(), nums.end());
int n = nums.size();
for(int i=0; i<nums.size();i++){
//如果n在数组当中 从小到大一次判断哪个数不在数组中
if(nums[i] != i){
return i;
}
}
//否则没有找到 那么就是n这个数
return n;
}
};

414. 第三大的数

给你一个非空数组,返回此数组中 第三大的数 。如果不存在,则返回数组中最大的数。

示例 1:
输入:[3, 2, 1]
输出:1
解释:第三大的数是 1 。

示例 2:
输入:[1, 2]
输出:2
解释:第三大的数不存在, 所以返回最大的数 2 。

示例 3:
输入:[2, 2, 3, 1]
输出:1
解释:注意,要求返回第三大的数,是指在所有不同数字中排第三大的数。
此例中存在两个值为 2 的数,它们都排第二。在所有不同数字中排第三大的数为 1 。

提示:
1 <= nums.length <= 104
-231 <= nums[i] <= 231 - 1

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
class Solution {
public:

int thirdMax(vector<int>& nums) {
//对所给数组进行从小到大排序
sort(nums.begin(), nums.end());

set<int> s;
int len = nums.size();
for(int i=0; i<len; i++){
//将元素加入无重复的集合中
s.insert( nums[i] );
}

//清空vector
nums.clear();
for(set<int>::iterator it=s.begin();it!=s.end();it++){
//将集合中的元素 加入数组中
nums.push_back(*it);
}

//如果数组的长度小于3 那么返回数组的最后一个元素
if(nums.size()<3) return nums[nums.size()-1];

//否则返回倒数第三个
return nums[nums.size()-3];
}
};


1004: 母牛的故事

题目描述
有一头母牛,它每年年初生一头小母牛。每头小母牛从第四个年头开始,每年年初也生一头小母牛。请编程实现在第n年的时候,共有多少头母牛?

输入
输入数据由多个测试实例组成,每个测试实例占一行,包括**一个整数n(0<n<55)**,n的含义如题目中描述。
n=0表示输入数据的结束,不做处理。

输出
对于每个测试实例,输出在第n年的时候母牛的数量。
每个输出占一行。

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
#include<iostream>
#include<vector>
#define N 100
using namespace std;

int fun(int n){
int a[N];
int i;
//避免索引错位 因此直接让a[1]=1...
for(int i=1; i<=4; i++){
a[i] = i;
}
//索引从第五年开始 状态转移方程是 ai = ai-1 + ai-3
for(i=5; i<=n; i++){
a[i] = a[i-1] + a[i-3];
}

//返回该数的数组位置
return a[n];
}

int main(){
int y = 0;
while(cin >> y){
if(y == 0)
break;
cout << fun(y) <<endl;
}
return 0;
}

434. 字符串中的单词数

统计字符串中的单词个数,这里的单词指的是连续的不是空格的字符。

请注意,你可以假定字符串里不包括任何不可打印的字符。

示例:

输入: “Hello, my name is John”
输出: 5
解释: 这里的单词是指连续的不是空格的字符,所以 “Hello,” 算作 1 个单词。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
class Solution {
public:
int countSegments(string s) {
//flag stands for if it is the Number
//count stands for the number of Num
int flag=0,count = 0;

for(int i=0; s[i] != '\0'; i++)
{
if(s[i] == ' '){
flag = 0;
}else if(flag == 0){
count++;
flag = 1;
}
}
return count;
}
};

392. 判断子序列

给定字符串 s 和 t ,判断 s 是否为 t 的子序列。
字符串的一个子序列是原始字符串删除一些(也可以不删除)字符而不改变剩余字符相对位置形成的新字符串。(例如,”ace”是”abcde”的一个子序列,而”aec”不是)。

示例 1:
输入:s = “abc”, t = “ahbgdc”
输出:true

示例 2:
输入:s = “axc”, t = “ahbgdc”
输出:false
 
提示:
0 <= s.length <= 100
0 <= t.length <= 10^4
两个字符串都只由小写字符组成。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
class Solution {
public:
bool isSubsequence(string s, string t) {
bool flag = true;
int i,j = -1;

for(int i=0; s[i] != '\0'; i++)
{
//从s中找各个字符 对应在t中的位置
j = t.find(s[i]);
if(j != string::npos){
//如果没找到 就返回false
//否则截取找到的位置 下一个位置到结束
//继续往后找
t = t.substr(j+1);
}else{
flag = false;
return flag;
}
}
return flag;
}
};

551. 学生出勤记录 I

给定一个字符串来代表一个学生的出勤记录,这个记录仅包含以下三个字符:

‘A’ : Absent,缺勤
‘L’ : Late,迟到
‘P’ : Present,到场
如果一个学生的出勤记录中不超过一个’A’(缺勤)并且不超过两个连续的’L’(迟到),那么这个学生会被奖赏。

你需要根据这个学生的出勤记录判断他是否会被奖赏。

示例 1:
输入: “PPALLP”
输出: True

示例 2:
输入: “PPALLL”
输出: False

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
class Solution {
public:

bool checkRecord(string s) {
bool flag = false;
int countA=0, countL=s.find("LLL");

for(int i=0; i<s.size(); i++){
if(s[i] == 'A'){
//对于不用连续出现的A 通过统计即可
countA++;
}
}

//对于连续出现L 可以看成是否出现 不满足题目要求的“字串” "LLL"即可
if(countL==string::npos && countA <= 1){
flag = true;
}
return flag;
}
};

面试题 01.03. URL化

URL化。编写一种方法,将字符串中的空格全部替换为%20。
假定该字符串尾部有足够的空间存放新增字符,并且知道字符串的“真实”长度。
(注:用Java实现的话,请使用字符数组实现,以便直接在数组上操作。)

示例 1:
输入:”Mr John Smith “, 13
输出:”Mr%20John%20Smith”
 
示例 2:
输入:” “, 5
输出:”%20%20%20%20%20”

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
class Solution {
public:
string replaceSpaces(string S, int length) {
string s = ""; //用一个新的字符串来装
for(int i=0; i<length; i++){
if(S[i] == ' '){
s += "%20";
}else{
s.push_back(S[i]);
}
}
cout << s;
return s;
}
};

459. 重复的子字符串(巧妙)

给定一个非空的字符串,判断它是否可以由它的一个子串重复多次构成。给定的字符串只含有小写英文字母,并且长度不超过10000。

示例 1:
输入: “abab”
输出: True
解释: 可由子字符串 “ab” 重复两次构成。

示例 2:
输入: “aba”
输出: False

示例 3:
输入: “abcabcabcabc”
输出: True
解释: 可由子字符串 “abc” 重复四次构成。 (或者子字符串 “abcabc” 重复两次构成。)

1
2
3
4
5
6
7
8
9
10
11
12
13
class Solution {
public:
bool repeatedSubstringPattern(string s) {
//如果是可用 子串重复 的串(比如abab)
//那么本身轮回一圈后 下次找一定可以在 小于这个串长度的位置里
//找到自身的串首次出现的位置

//否则如果不是可重复的(比如ab)
//本身轮回一圈后 下次再找到自己的串ab 一定不在自身的长度以内 abab
return (s + s).find(s, 1) != s.size();
}
};

506. 相对名次

给出 N 名运动员的成绩,找出他们的相对名次并授予前三名对应的奖牌。
前三名运动员将会被分别授予 “金牌”,“银牌” 和“ 铜牌”(”Gold Medal”, “Silver Medal”, “Bronze Medal”)。
(注:分数越高的选手,排名越靠前。)

示例 1:
输入: [5, 4, 3, 2, 1]
输出: [“Gold Medal”, “Silver Medal”, “Bronze Medal”, “4”, “5”]
解释: 前三名运动员的成绩为前三高的,因此将会分别被授予 “金牌”,“银牌”和“铜牌” (“Gold Medal”, “Silver Medal” and “Bronze Medal”).
余下的两名运动员,我们只需要通过他们的成绩计算将其相对名次即可。

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
class Solution {
public:

static bool cmp(int a, int b){
return a>b;
}

vector<string> findRelativeRanks(vector<int>& score) {
vector<string> v;
unordered_map<int, int> m;
int num = 1; //根据分数 从高(第一名)到低进行排名
string gold = "Gold Medal";
string silver = "Silver Medal";
string bronze = "Bronze Medal";

vector<int> score1 = score; //新建一个数组 用来记录分数对应的名词

sort(score1.begin(), score1.end(), cmp); //最高分的排在前面

for(int i=0; i<score1.size(); i++){
m[score1[i]] = num++; //开始记录
}

for(int i=0; i<score.size(); i++){
int n = m[score[i]]; //根据自己的元素 原地取对应的排名

//修改前三名的string(金银铜)
if(n == 1){
v.push_back(gold);
continue;
}
if(n == 2){
v.push_back(silver);
continue;
}
if(n == 3){
v.push_back(bronze);
continue;
}
v.push_back(to_string(n));
}

for(string str:v){
cout << str << " ";
}
return v;
}
};