龙珠计划python训练营
天池龙珠计划Python训练营本次学习中,我们尝试了数据分析的方法,运用部分的python包实现了图片扣底、热力图绘制、统计图的绘制等数据分析和数据挖掘内容。主要运用pandas等python标准库。
Windows环境安装anaconda, pytorch
因为日常使用的windows,需要在windows环境下安装一套anaconda,还有需要使用的pytorch库。打开搜索引擎,搜索 清华大学镜像站 anaconda第一的就是镜像站点,点击链接打开。按页面提示打开下载地址页面https://mirrors.tuna.tsinghua.edu.cn/anaconda/archive/CTRL+F搜索2022,找到最新版本的windows x86_64安装程序,点击后可以下载文件下载完成后,双击打开,按照界面提示,是常用的windows软件安装过程安装完成后,从开始菜单打开Anaconda Navigator可以查看已有的组件,环境如果要新建环境,打开Environments标签,点击Create按钮,弹出框输入名称,使用的python版本号,然后点Create新的环境创建后,安装需要使用的pytorch库打开https://pytorch.org/,选择安装选项生成的命令行为pip3 install torch torchvision torchaudio在newenv1环境上点展开按钮打开Open Terminal,输入命令行安装pytorch检查pytorch是否已安装可以看已安装的torch版本为1.11.0+cpu,安装完成
飞天加速计划·高校学生在家实践——教务系统查成绩Python爬虫程序
我就读于自动化专业,现为一名大三学生。本学期学习了“智能控制终端课程”,教学内容包括网络与通信基础、基于C++的Qt界面开发、Linux入门等。在上个学期末,也就是大三上考完试后,我觉得查考试成绩十分地繁琐。于是编写了一个Python爬虫程序帮我去教务系统中爬取成绩,打印成绩单并计算GPA。在本学期的Linux入门学习中,了解到除了在自己电脑上装虚拟机,或是在电脑上装双系统,也可以购买租赁阿里云服务器。于是,我通过飞天加速计划·高校学生在家实践活动获得了两周的免费阿里云ECS使用机会。我花了一个晚上的时间熟悉了SSH,并扩充了之前的教务系统查成绩爬虫代码,将Python程序运行在阿里云ECS上。在官网的教程指导下,从服务器租赁到程序部署,这个过程非常快。下面来介绍一下我的教务系统查成绩Python程序整个程序的实现步骤分为以下几部分:1.教务系统爬虫2.发邮件3.整合1和2到一个py脚本中4.部署到阿里云Linux服务器除了py脚本,还需要在同一个路径下创建一个名为1.txt的文本文档,用于存放上一次查询时,出了几门课的成绩,比如:上一次查询出了3门课的成绩,那么1.txt文档的内容就是31.教务系统爬虫我们学校的教务系统是正方软件股份有限公司开发的,实现的思路是:在浏览器里打开教务系统,找到查成绩的页面打开浏览器检查功能,刷新网页,找到FXH文件,一般成绩会存在一个json格式的文件里用python的requests库进行带参数的请求,带上headers、data,cookie会在请求头里从json文件中提取成绩相关的元素,存入变量import requests
headers = {} # 可以在浏览器中用检查找到请求头等信息
data = {}
url = 'https://jwxt.cjlu.edu.cn/cjcx/cjcx_cxXsgrcj.html?'
res = requests.post(url, headers = headers, data = data)
json = res.json()
text = text + "\r\n{} {} {} {}".format('课程名称'.center(10, chr(12288)), '学分'.center(4, chr(12288)), '成绩'.center(4, chr(12288)), '绩点'.center(4, chr(12288)))
sum_credit_gp = 0.0
sum_credit = 0.0
for each in json['items']:
subject = each['kcmc'] # 课程名称
credit = each['xf'] # 学分
grade = each['bfzcj'] # 成绩
gradepoint = each['jd'] # 绩点
credit_gp = float(credit) * float(gradepoint) # 学分绩点 = 学分*绩点
sum_credit = sum_credit + float(credit)
sum_credit_gp = sum_credit_gp + credit_gp # 计算GPA
text = text + "\r\n{} {} {} {}".format(subject.center(10, chr(12288)), credit.center(4, chr(12288)), grade.center(4, chr(12288)), gradepoint.center(4, chr(12288)))
#with open("/home/yrl/request_grade/1.txt", 'r') as f: # 部署到linux系统中,使用绝对路径
with open("1.txt", 'r') as f: # 1.txt存储上一次num的数值
num = f.read() # 出了几门课的成绩,num就是几
if num == str(len(json['items'])):
print("没有变化")
# 不发送邮件
if num!=str(len(json['items'])):
#with open("/home/yrl/request_grade/1.txt", 'w') as f:
with open("1.txt", 'w') as f:
print("发生变化,出了新的成绩")
# 发送邮件
self.send_mail()
# 并修改txt文件
f.write(str(len(json['items'])))2.发邮件import smtplib #调用smtplib模块 用于发信动作
from email.mime.text import MIMEText #调用MIMEText方法 构建邮件内容
from email.header import Header #从email包引入Header()方法 构建邮件头
from_addr = "
[email protected]"
password = "xxxxx" #POP 授权码
to_addr = "
[email protected]"
smtp_server = 'smtp.qq.com' #发信服务器
title = '请输入邮件标题'
text = '请输入正文内容'
msg = MIMEText(text,'plain','utf-8') #正文内容 参1为正文内容 参2为格式(plain为纯文本) 参3为编码
msg['From'] = Header(from_addr) #构建邮件头
msg['To'] = Header(to_addr) #构建邮件头
msg['Subject'] = Header(title) #构建邮件头
server = smtplib.SMTP_SSL(smtp_server) #开启发信服务,这里使用的是加密传输
server.connect(smtp_server,465)
server.login(from_addr, password) #登录
server.sendmail(from_addr, to_addr, msg.as_string()) #发送 参1发件人 参2收件人 参3"内容"
server.quit() #关闭服务器
print('邮件已发送')3.将1和2整合到一个py脚本中import requests
import smtplib #调用smtplib模块 用于发信动作
from email.mime.text import MIMEText #调用MIMEText方法 构建邮件内容
from email.header import Header #从email包引入Header()方法 构建邮件头
class RequestGrade:
text = ""
def send_mail(self):
from_addr = "
[email protected]"
password = "xxxxx" #POP 授权码
to_addr = "
[email protected]"
smtp_server = 'smtp.qq.com' #发信服务器
title = '出了新的成绩'
msg = MIMEText(self.text,'plain','utf-8') #正文内容 参1为正文内容 参2为格式(plain为纯文本) 参3为编码
msg['From'] = Header(from_addr) #构建邮件头
msg['To'] = Header(to_addr) #构建邮件头
msg['Subject'] = Header(title) #构建邮件头
server = smtplib.SMTP_SSL(smtp_server) #开启发信服务,这里使用的是加密传输
server.connect(smtp_server,465)
server.login(from_addr, password) #登录
server.sendmail(from_addr, to_addr, msg.as_string()) #发送 参1发件人 参2收件人 参3"内容"
server.quit() #关闭服务器
print('邮件已发送')
def get_grade(self):
headers = {}
data = {}
url = 'https://jwxt.cjlu.edu.cn/cjcx/cjcx_cxXsgrcj.html?'
res = requests.post(url, headers = headers, data = data)
json = res.json()
print("\n{} {} {} {}".format('课程名称'.center(10, chr(12288)), '学分'.center(4, chr(12288)), '成绩'.center(4, chr(12288)), '绩点'.center(4, chr(12288))))
self.text = self.text + "\r\n{} {} {} {}".format('课程名称'.center(10, chr(12288)), '学分'.center(4, chr(12288)), '成绩'.center(4, chr(12288)), '绩点'.center(4, chr(12288)))
sum_credit_gp = 0.0
sum_credit = 0.0
for each in json['items']:
subject = each['kcmc']
credit = each['xf']
grade = each['bfzcj']
gradepoint = each['jd']
credit_gp = float(credit) * float(gradepoint)
sum_credit = sum_credit + float(credit)
sum_credit_gp = sum_credit_gp + credit_gp
print("{} {} {} {}".format(subject.center(10, chr(12288)), credit.center(4, chr(12288)), grade.center(4, chr(12288)), gradepoint.center(4, chr(12288))))
self.text = self.text + "\r\n{} {} {} {}".format(subject.center(10, chr(12288)), credit.center(4, chr(12288)), grade.center(4, chr(12288)), gradepoint.center(4, chr(12288)))
print('\n\t\tGPA:{:.5f}'.format(sum_credit_gp / sum_credit))
self.text = self.text + ('\r\n\t\tGPA:{:.5f}'.format(sum_credit_gp / sum_credit))
#with open("/home/yrl/request_grade/1.txt", 'r') as f:
with open("1.txt", 'r') as f:
num = f.read() # 出了几门课的成绩
if num == str(len(json['items'])):
print("没有变化")
# 不发送邮件
if num!=str(len(json['items'])):
#with open("/home/yrl/request_grade/1.txt", 'w') as f:
with open("1.txt", 'w') as f:
print("发生变化,出了新的成绩")
# 发送邮件
self.send_mail()
# 并修改txt文件
f.write(str(len(json['items'])))
if __name__ == "__main__":
r = RequestGrade()
r.get_grade()4.在阿里云服务器上定时执行程序我没有选Ubuntu或CentOS,因为他们自带的是Python版本是Python 2,而Alibaba Cloud Linux自带了Python 3。注意:需要提前装好pip包管理工具,并安装requests、smtplib等库接下来就可以把我们的程序部署到服务器里啦在终端定时运行这个程序编辑定时任务crontab -e
每分钟都运行一次* * * * * python main.py以上就是教务系统爬虫Python程序的源代码了。我的Python和Linux基础都较为一般,代码也有些许不足或让人不易理解,请多多体谅。感谢阿里云-高校学生在家实践活动给我提供了这个机会,让我将理论与实践更好地相结合,让我有实操使用Linux服务器的机会。我在这个过程中也遇到了一些问题,可以给新手一些tips:1.服务器的端口可以不要选择默认的,不然睡一觉醒来,就会发现有几百条访问失败的记录,这应该是其他人对服务器在进行攻击2.同第一个问题,为了提高安全性,建议把密码设置地更复杂一些3.阿里云也提供了iPad和iOS的软件,可以直接使用SSH登陆,非常方便希望未来能进一步深入学习,分享一些更优质的原创作品
Python每日一练——第1天:水仙花数
1. 问题描述水仙花数也被称为超完全数字不变数、自恋数、自幂数、阿姆斯壮数或阿姆斯特朗数,水仙花数是指一个3位数,它的每个位上的数字的3次幂之和等于它本身。1、水仙花数是一个三位数:111 333 456 999 5302、水仙花数的个位、十位、百位的数字立方和等于原数小伙伴们看了问题描述后,一定要自己先练习,再去看博主的代码和解题思路,才能提高自己的编程水平,全靠自觉哟!!!2. 问题分析怎么获取个位、十位、百位上的数?个位数37==1== :就是原始数字对10进行取余的运算结果 37==1== % 10 = ==1==十位数3==7==1:3==7==1通过除以10,可以将7移动到个位上去(整数):3==7==1 // 10 = 3==7==3==7==:3==7==对10进行取余可以得到最后一位的值==7== :3==7== % 10 = ==7==百位数==3==71:==3==就是原始数字除以100的结果(整除):==3==71 // 100 = ==3==思考:任意数字的指定位置上的数值如何求?1234==5==6789:先10000得到1234==5==;再对10取余得到==5==3. 算法思路1. 使用循环从100开始到999结束2. 每次的循环体内,获取百位数数字、十位数数字、个位数数字3. 判断百位数数字三次方加十位数数字的三次方加个位数数字的三次方是否等于它本身,如果是就是水仙花数。4. 代码实现for循环代码实现实现代码:print('100到1000之前的所有水仙花数如下:')
for i in range(100, 1000):
# 取百位数字 371 // 100 = 3
x = i // 100
# 取十位数 371 // 10 =3 7; 37 % 10 = 7
y = i // 10 % 10
# 取个位数 371 % 10 = 1
z = i % 10
# 判断个位、十位、百位的数字立方和等于原数
if x ** 3 + y ** 3 + z ** 3 == i:
print(f'{i}是水仙花数')运行结果:while循环代码实现实现代码:print('100到1000之前的所有水仙花数如下:')
number = 100
while number < 1000:
# 取百位数字 371 // 100 = 3
x = number // 100
# 取十位数 371 // 10 =3 7; 37 % 10 = 7
y = number // 10 % 10
# 取个位数 371 % 10 = 1
z = number % 10
# 判断个位、十位、百位的数字立方和等于原数
if x ** 3 + y ** 3 + z ** 3 == number:
print(f'{number}是水仙花数')
# 需要设置number每次加一
number += 1运行结果:5. 如何让刷题变得更加高效呢?1. 编程小白选手很多刚入门编程的小白学习了基础语法,却不知道语法的用途,不知道如何加深映像,不知道如何提升自己,这个时候每天刷自主刷一道题就非常重要(百炼成神),可以去牛客网上的编程初学者入门训练。该专题为编程入门级别,适合刚学完语法的小白练习,题目涉及编程基础语法,基本结构等,每道题带有练习模式和考试模式,可还原考试模式进行模拟,也可通过练习模式进行练习。链接地址:牛客网 | 编程初学者入门训练2. 编程进阶选手当基础练习完已经逐步掌握了各知识要点后,这个时候去专项练习中学习数据结构、算法基础、计算机基础等。先从简单的入手,感觉上来了再做中等难度,以及较难的题目。这三样是面试中必考的知识点,我们只有坚持每日自己去多加练习,拒绝平躺持续刷题,不断提升自己才能冲击令人满意的公司。链接地址:牛客网 | 专项练习速度上号,大家一起冲击大厂,有疑问评论区留言解答!!!
7月博主有奖征文,百分百得奖
活动人群:面向阿里云开发者社区入驻博主(技术/星级/专家),本月新发文两篇,除享受本身级别奖励外,同步获得云小宝抱枕一个,百分百得奖。表单提交地址:https://survey.aliyun.com/apps/zhiliao/q9gQIssr-活动规则:1、活动面向阿里云开发者社区入驻博主(技术/星级/专家)如未入驻,请先发文3篇申请入驻。乘风者博主入驻申请表:https://survey.aliyun.com/apps/zhiliao/LFF0Fd3tX2、参与本活动新发布的两篇文章发布且通过审核时间需在2022年7月1日—31日之间,数量最低要求为2篇。3、文章内容需要符合社区审核规范,技术干货类内容,文章字数需要达到1000字及以上,且格式整齐规范,尽量图文并茂。4、文章涵盖的技术方面为java、python、前端、后端、大数据、人工智能、大数据、算法、对阿里云产品的评测等(不包含参赛文章)等5、活动中的“天”、“工作日”等均指该日的0点至24点(北京时间)6、阿里云可以根据活动的实际情况对活动规则进行变动调整,相关变动或调整将公布在活动页面上。并于公布时间即时生效;但不影响用户在活动规则调整前已经获得的权益。月度发文,我们将通过“文末感兴趣的人”评估出最佳文章三篇,赠送云小宝奥运手办套装礼盒。
龙珠计划python训练营
天池龙珠计划Python训练营本次学习了python中有关于自定义函数DEFCLALSSDENG的知识使用def进行函数的定义,其中,需要确定位置等参数此外,了解了变量域的知识。同时还掌握了匿名函数的运用
【每日算法Day 80】所有人都会做的入门题,高级解法来了!
题目链接LeetCode 面试题 08.01. 三步问题[1]题目描述示例1输入:n = 3 输出:4解释:有四种走法示例2输入:n = 5输出:13题解昨天的题解地址:【每日算法Day 79】所有人都会做的入门题,但是能看出你的代码能力!韦阳的博客:【每日算法Day 79】所有人都会做的入门题,但是能看出你的代码能力![2]知乎专栏:【每日算法Day 79】所有人都会做的入门题,但是能看出你的代码能力![3]代码c++typedef long long ll;typedef vector<vector<ll>> vvl;typedef vector<ll> vl;const ll p = 1e9+7;
class Solution {
public:
vvl mat_mul(vvl& A, vvl& B) {
int a = A.size(), b = B.size(), c = B[0].size();
vvl C(a, vl(c, 0));
for (int i = 0; i < a; ++i) {
for (int j = 0; j < c; ++j) {
for (int k = 0; k < b; ++k) {
(C[i][j] += A[i][k] * B[k][j]) %= p;
}
}
}
return C;
}
vvl mat_pow(vvl& A, int n) {
int m = A.size();
vvl B(m, vl(m, 0));
for (int i = 0; i < m; ++i) B[i][i] = 1;
while (n > 0) {
if (n&1) B = mat_mul(B, A);
A = mat_mul(A, A);
n >>= 1;
}
return B;
}
vvl mat_pow_rec(vvl& A, int n) {
if (n == 1) return A;
vvl B = mat_pow_rec(A, n/2);
B = mat_mul(B, B);
if (n&1) return mat_mul(A, B);
return B;
}
int waysToStep(int n) {
vl f = {1, 2, 4};
if (n <= 3) return f[n-1];
vvl A = {{0, 0, 1}, {1, 0, 1}, {0, 1, 1}};
vvl B = mat_pow(A, n-3);
ll res = 0;
for (int i = 0; i < 3; ++i) {
(res += f[i] * B[i][2]) %= p;
}
return res;
}
};pythonimport numpy as np
class Solution:
def mat_pow(self, A, n):
m = A.shape[0]
B = np.eye(m, dtype=np.int64)
while n > 0:
if (n&1)!=0:
B = np.mod(np.matmul(B, A), self.p).astype(np.int64)
A = np.mod(np.matmul(A, A), self.p).astype(np.int64) n >>= 1
return B;
def waysToStep(self, n: int) -> int:
self.p = int(1e9+7)
f = [1, 2, 4]
if n <= 3: return f[n-1]
A = np.array([[0, 0, 1], [1, 0, 1], [0, 1, 1]],
dtype=np.int64)
B = self.mat_pow(A, n-3)
res = 0
for i in range(3):
res += f[i] * B[i][2]
return int(res%self.p)参考资料[1]LeetCode 面试题 08.01. 三步问题: https://leetcode-cn.com/problems/three-steps-problem-lcci/[2]韦阳的博客:【每日算法Day 79】所有人都会做的入门题,但是能看出你的代码能力!: https://godweiyang.com/2020/03/24/leetcode-inteview-08-01/[3]知乎专栏:【每日算法Day 79】所有人都会做的入门题,但是能看出你的代码能力!: https://zhuanlan.zhihu.com/p/115799226作者简介:godweiyang,知乎同名,华东师范大学计算机系硕士在读,方向自然语言处理与深度学习。喜欢与人分享技术与知识,期待与你的进一步交流~
【每日算法Day 97】经典面试题:求两个数组最小差
题目链接LeetCode 面试题 16.06. 最小差[1]题目描述给定两个整数数组 a 和 b,计算具有最小差绝对值的一对数值(每个数组中取一个值),并返回该对数值的差。说明:1 <= a.length, b.length <= 100000-2147483648 <= a[i], b[i] <= 2147483647正确结果在区间 [-2147483648, 2147483647] 内示例1输入:{1, 3, 15, 11, 2}, {23, 127, 235, 19, 8}输出:3,即数值对(11, 8)题解代码c++class Solution {
public:
int smallestDifference(vector<int>& a, vector<int>& b) {
sort(a.begin(), a.end());
sort(b.begin(), b.end());
int n = a.size(), m = b.size();
int i = 0, j = 0;
long res = INT_MAX;
while (i < n && j < m) {
res = min(res, abs(long(a[i])-long(b[j])
)
);
if (a[i] > b[j]) ++j;
else ++i;
}
return res;
}
};pythonclass Solution:
def smallestDifference(self, a: List[int], b: List[int]) -> int:
a.sort()
b.sort()
n, m = len(a), len(b)
i, j, res = 0, 0, 2147483647
while i < n and j < m:
res = min(res, abs(a[i]-b[j]))
if a[i] > b[j]: j += 1
else: i += 1
return res参考资料[1]LeetCode 面试题 16.06. 最小差: https://leetcode-cn.com/problems/smallest-difference-lcci/作者简介:godweiyang,知乎同名,华东师范大学计算机系硕士在读,方向自然语言处理与深度学习。喜欢与人分享技术与知识,期待与你的进一步交流~
【每日算法Day 96】腾讯面试题:合并两个有序数组
题目链接LeetCode 88. 合并两个有序数组[1]题目描述给你两个有序整数数组 nums1 和 nums2,请你将 nums2 合并到 nums1 中,使 nums1 成为一个有序数组。说明:初始化 nums1 和 nums2 的元素数量分别为 m 和 n 。你可以假设 nums1 有足够的空间(空间大小大于或等于 m + n)来保存 nums2 中的元素。示例1输入:nums1 = [1,2,3,0,0,0], m = 3nums2 = [2,5,6], n = 3输出:[1,2,2,3,5,6]解释:题解看到这道题,脑海里应该第一时间想到的是归并排序,但是归并排序需要一个额外的数组用来保存排序后的数组,这里不允许使用额外空间。那么我们还是用归并排序的思路来做,试一下两个指针 i = 0 和 j = 0 ,初始的时候分别指着 nums1[0] 和 nums2[0] 。然后比较 nums1[i] 和 nums2[j] 大小,如果 nums1[i] 更小,那么就放在原位不动它,然后 i += 1。如果 nums2[j] 更小,那么就交换 nums1[i] 和 nums2[j] ,然后还是 i += 1。这么看貌似可行哦?但是最终一定会先遍历完 nums1,然后 j 还是停留在 0 ,然后你会发现 nums2 中的数字还是乱序的,根本没法处理。那么怎么利用上 nums1 后面多出的那么多空位呢?我们可以换个思路,从最大的开始遍历。两个指针初始的时候 i = m-1 和 j = n-1 ,然后将较大值填充到 nums1 的最后面。最后如果 nums2 中还有剩余,就依次填充到 nums1 最前面就行了。这样为什么就可以了呢?因为如果从小到大遍历的话,元素会覆盖掉 nums1 中还没遍历的元素。但是从大到小是填充到尾部,就不会产生覆盖。就算极限情况下 nums2 中元素全部大于 nums1 中元素,也不会覆盖到 nums1 的最后一个元素。面试官最后还会问你有啥优化,我当时图省事,最后还把 nums1 中剩下元素填充到 nums1 最前面了,其实完全没有必要,本来就是有序的,等于没有做事。代码c++class Solution {
public:
void merge(vector<int>& nums1, int m, vector<int>& nums2, int n)
{
int i = m-1, j = n-1, k = m+n-1
; while (i >= 0 && j >= 0) {
if (nums1[i] > nums2[j]) nums1[k--] = nums1[i--];
else nums1[k--] = nums2[j--];
}
while (j >= 0) nums1[k--] = nums2[j--];
}
};pythonclass Solution:
def merge(self, nums1: List[int], m: int, nums2: List[int], n:
int) -> None:
i, j = m-1, n-1
while i >= 0 and j >= 0:
if nums1[i] > nums2[j]:
nums1[i+j+1] = nums1[i]
i -= 1
else:
nums1[i+j+1] = nums2[j]
j -= 1
while j >= 0:
nums1[j] = nums2[j]
j -= 1参考资料[1]LeetCode 88. 合并两个有序数组: https://leetcode-cn.com/problems/merge-sorted-array/作者简介:godweiyang,知乎同名,华东师范大学计算机系硕士在读,方向自然语言处理与深度学习。喜欢与人分享技术与知识,期待与你的进一步交流~
【每日算法Day 93】不用额外空间,你会旋转一个矩阵吗?
题目链接LeetCode 面试题 01.07. 旋转矩阵[1]题目描述给你一幅由 N × N 矩阵表示的图像,其中每个像素的大小为 4 字节。请你设计一种算法,将图像旋转 90 度。不占用额外内存空间能否做到?示例1给定 matrix = [ [1,2,3], [4,5,6], [7,8,9]],原地旋转输入矩阵,使其变为:[ [7,4,1], [8,5,2], [9,6,3]]示例2给定 matrix =[ [ 5, 1, 9,11], [ 2, 4, 8,10], [13, 3, 6, 7], [15,14,12,16]], 原地旋转输入矩阵,使其变为:[ [15,13, 2, 5], [14, 3, 4, 1], [12, 6, 8, 9], [16, 7,10,11]]题解旋转可以发现,每个格子旋转四次之后都会回到原位。所以对于每个格子,我们只需要交换和它相关的一共四个格子的位置就行了。对于格子 (i, j) ,我们可以推算出它旋转后的三个新位置是 (j, n-1-i), (n-1-i, n-1-j), (n-1-j, i) 。所以只需要一个临时变量保存其中一个位置的值,然后按顺序交换位置就行了。当然为了避免重复旋转,我们只能枚举四分之一的格子,如果 n 是偶数,如下图所示,我们可以这划分:如果 n 是奇数,可以如下图这么划分:当然你也可以不规则的划分,如下图这样,只是代码写起来有点费劲:翻转这题还可以不通过模拟旋转来实现旋转。上面说过了,格子 (i, j) 旋转后的新位置是 (j, n-1-i) 。那么我们可以先沿着主对角线翻转矩阵,这样格子 (i, j) 位置就换到了 (j, i) 。然后再左右翻转一下矩阵,格子 (j, i) 就换到了 (j, n-1-i) ,正好等价于旋转后的位置!因为翻转每次只需要交换两个格子的位置,所以不需要任何额外变量。再提一个交换两个元素的小 trick ,如代码里注释的那样,可以采用异或操作来规避额外变量。代码旋转(c++)class Solution {
public:
void rotate(vector<vector<int>>& matrix) {
int n = matrix.size();
for (int i = 0; i < n/2; ++i) {
for (int j = 0; j < (n+1)/2; ++j) {
int tmp = matrix[n-1-j][i];
matrix[n-1-j][i] = matrix[n-1-i][n-1-j];
matrix[n-1-i][n-1-j] = matrix[j][n-1-i];
matrix[j][n-1-i] = matrix[i][j];
matrix[i][j] = tmp;
}
}
}
};翻转(c++)class Solution {
public:
void rotate(vector<vector<int>>& matrix) {
int n = matrix.size();
for (int i = 0; i < n; ++i) {
for (int j = i+1; j < n; ++j) {
matrix[i][j] ^= matrix[j][i];
matrix[j][i] ^= matrix[i][j];
matrix[i][j] ^= matrix[j][i];
// swap(matrix[i][j], matrix[j][i]);
}
}
for (int i = 0; i < n; ++i) {
for (int j = 0; j < n/2; ++j) {
matrix[i][j] ^= matrix[i][n-1-j];
matrix[i][n-1-j] ^= matrix[i][j];
matrix[i][j] ^= matrix[i][n-1-j];
// swap(matrix[i][j], matrix[i][n-1-j]);
}
}
}
};旋转(python)class Solution:
def rotate(self, matrix: List[List[int]]) -> None:
n = len(matrix)
for i in range(n//2):
for j in range((n+1)//2):
tmp = matrix[n-1-j][i]
matrix[n-1-j][i] = matrix[n-1-i][n-1-j]
matrix[n-1-i][n-1-j] = matrix[j][n-1-i]
matrix[j][n-1-i] = matrix[i][j]
matrix[i][j] = tmp翻转(python)class Solution:
def rotate(self, matrix: List[List[int]]) -> None:
n = len(matrix)
for i in range(n):
for j in range(i+1, n):
matrix[i][j], matrix[j][i] = matrix[j][i], matrix[i]
[j]
for i in range(n):
for j in range(n//2):
matrix[i][j], matrix[i][n-1-j] = matrix[i]
[n-1-j], matrix[i][j]关注【算法码上来】,每日算法干货马上就来!参考资料[1]LeetCode 面试题 01.07. 旋转矩阵: https://leetcode-cn.com/problems/rotate-matrix-lcci/作者简介:godweiyang,知乎同名,华东师范大学计算机系硕士在读,方向自然语言处理与深度学习。喜欢与人分享技术与知识,期待与你的进一步交流~