首页
壁纸
留言板
友链
更多
统计归档
Search
1
TensorBoard:训练日志及网络结构可视化工具
12,575 阅读
2
主板开机跳线接线图【F_PANEL接线图】
6,426 阅读
3
Linux使用V2Ray 原生客户端
5,743 阅读
4
移动光猫获取超级密码&开启公网ipv6
3,632 阅读
5
NVIDIA 显卡限制功率
3,031 阅读
好物分享
实用教程
linux使用
wincmd
学习笔记
mysql
java学习
nginx
综合面试题
大数据
网络知识
linux
放码过来
python
javascript
java
opencv
蓝桥杯
leetcode
深度学习
开源模型
相关知识
数据集和工具
模型轻量化
语音识别
计算机视觉
杂七杂八
硬件科普
主机安全
嵌入式设备
其它
bug处理
登录
/
注册
Search
标签搜索
好物分享
学习笔记
linux
MySQL
nvidia
typero
内网穿透
webdav
vps
java
cudann
gcc
cuda
树莓派
CNN
图像去雾
ssh安全
nps
暗通道先验
阿里云
jupiter
累计撰写
354
篇文章
累计收到
69
条评论
首页
栏目
好物分享
实用教程
linux使用
wincmd
学习笔记
mysql
java学习
nginx
综合面试题
大数据
网络知识
linux
放码过来
python
javascript
java
opencv
蓝桥杯
leetcode
深度学习
开源模型
相关知识
数据集和工具
模型轻量化
语音识别
计算机视觉
杂七杂八
硬件科普
主机安全
嵌入式设备
其它
bug处理
页面
壁纸
留言板
友链
统计归档
搜索到
60
篇与
的结果
2023-05-17
python-opencv限制图片长宽实现图片压缩
1.业务背景图片压缩前的预处理,适配手机端图片大小显示且尽可能的减少图片存储空间的占用。通过限制图片的最大宽度和最大高度来减少图片的大小。2.核心代码import cv2 import os import shutil import math def img_compress_by_openCV(img_path_local,img_size_thresh = 300,max_height=2560,max_width=1440): # 压缩前图片大小 img_src_size = os.path.getsize(img_path_local)/1024 # 压缩后图片保存地址 img_path_compress = "./images/opencvs_"+img_path_local.split("/")[-1] # 若压缩前图片大小已经大小阈值img_size_thresh则跳过压缩 if(img_src_size<img_size_thresh): print("图片大小小于"+str(img_size_thresh)+"KB,跳过压缩"); shutil.copyfile(img_path_local,img_path_compress) else: print("openCV压缩前图片大小:"+str(int(img_src_size))+"KB") # 计算压缩比 img = cv2.imread(img_path_local) heigh, width = img.shape[:2] print("openCV压缩前图片尺寸(heigh, width)=:("+str(int(heigh))+","+str(int(width))+")") compress_rate = min(max_height/heigh,max_width/width,1) # 调用openCV进行图片压缩 img_compress = cv2.resize(img, (int(heigh*compress_rate), int(width*compress_rate)),interpolation=cv2.INTER_AREA) # 双三次插值 cv2.imwrite(img_path_compress, img_compress) # 压缩后图片大小 img_compress_size = os.path.getsize(img_path_compress)/1024 print("openCV压缩后图片大小:"+str(int(img_compress_size))+"KB") print("openCV压缩前图片尺寸(heigh, width)=:("+str(heigh*compress_rate)+","+str(int(width*compress_rate))+")") return img_path_compress img_path_local = "./images/1684155324391.jpg" img_path_compress = img_compress_by_openCV(img_path_local)运行结果openCV压缩前图片大小:2219KB openCV压缩前图片尺寸(heigh, width)=:(4000,3000) openCV压缩后图片大小:469KB openCV压缩前图片尺寸(heigh, width)=:(1920.0,1440)
2023年05月17日
495 阅读
0 评论
0 点赞
2023-05-15
python调用TinyPNG进行图片无损压缩
1.TinyPNG介绍TinyPNG是一种在线图片压缩工具,可以将图片压缩到更小的文件大小,而且不会对图片质量造成明显的影响。其实现原理主要是基于两个方面:压缩算法和颜色减少。压缩算法TinyPNG使用的是一种叫做Deflate的压缩算法。Deflate算法是一种无损压缩算法,可以将图片的二进制数据进行压缩,从而减小图片文件的大小。在Deflate算法中,压缩的主要思想是利用重复的数据进行替换,从而减小文件的大小。具体来说,Deflate算法主要包括两个步骤:压缩和解压缩。在压缩过程中,数据被分成多个块,并且每个块都有自己的压缩字典。在解压缩过程中,压缩字典用于还原压缩后的数据。2. 颜色减少另一个TinyPNG使用的技术是颜色减少。颜色减少是一种通过减少图片中使用的颜色数来减小文件大小的技术。在实践中,很多图片中使用的颜色实际上是不必要的,因此可以通过将这些颜色删除来减小文件的大小。具体来说,TinyPNG会先对图片进行一个预处理,找出图片中使用频率最低的颜色,并将其替换成使用频率更高的颜色。这个过程是基于一个叫做K-means的算法实现的。K-means算法是一种基于聚类的算法,可以将图片中使用的颜色分成多个聚类,从而找出使用频率最低的颜色。2.python调用TinyPNG API进行图片压缩安装依赖pip install tinify核心代码import tinify import os import shutil def img_compress_by_tinify(img_path_local,img_size_thresh = 200): if not os.path.exists("./images"): os.makedirs("./images") # 压缩前图片大小 img_src_size = os.path.getsize(img_path_local)/1024 # 压缩后图片保存地址 img_path_compress = "./images/compress_"+img_path_local.split("/")[-1] # 若压缩前图片大小已经大小阈值img_size_thresh则跳过压缩 if(img_src_size<img_size_thresh): print("图片大小小于"+str(img_size_thresh)+"KB,跳过压缩"); shutil.copyfile(img_path_local,img_path_compress) else: print("压缩前图片大小:"+str(int(img_src_size))+"KB") # 调用tinyPNG进行图片压缩 tinify.key = "V02hTQyPz4WRXPyCChGv6nJJTZYVtzcd" source = tinify.from_file(img_path_local) source.to_file(img_path_compress) # 压缩后图片大小 img_compress_size = os.path.getsize(img_path_compress)/1024 print("压缩后图片大小:"+str(int(img_compress_size))+"KB") return img_path_compress img_path_local = "./images/1684153992017.jpg" img_path_compress = img_compress_by_tinify(img_path_local) print(img_path_compress)调用结果压缩前图片大小:693KB 压缩后图片大小:148KB ./images/compress_1684153992017.jpg
2023年05月15日
478 阅读
0 评论
0 点赞
2023-05-15
python上传文件到阿里云oss
安装依赖包pip install oss2核心代码import oss2 access_key_id = 'LTA*******************' access_key_secret = 'ZAx*******************************' bucket_name = 'caucshop' endpoint = 'oss-cn-beijing.aliyuncs.com' # 创建bucket对象 bucket = oss2.Bucket(oss2.Auth(access_key_id, access_key_secret), endpoint, bucket_name) # 待上传的文件路径 file_path_local = "./Snipaste_2023-05-13_18-54-02.jpg" # 上传到oss后保保存的路径 file_path_oss = "goodImgsCompresss/"+file_path_local.split("/")[-1] # 读取文件 with open(file_path_local, "rb") as f: data = f.read() # 上传文件 bucket.put_object(file_path_oss, data) # 获取文件的url file_url_oss = "https://"+bucket_name+"."+endpoint+"/"+file_path_oss; print(file_url_oss)执行结果,得到文件在oss中的存储地址,我这里采用的是公共读的权限https://caucshop.oss-cn-beijing.aliyuncs.com/goodImgsCompresss/Snipaste_2023-05-13_18-54-02.jpg参考资料【python】 文件/图片上传 阿里云OSS ,获取外网链接 实例_oss图片外链_维玉的博客-CSDN博客
2023年05月15日
348 阅读
0 评论
0 点赞
2023-05-09
python文字转语音(可保存为mp3)
1.pyttsx3模块(亲测可用)这是一款优秀的文字转语音的模块,它生成的音频文件也比较具有个性化。可以调整声音的音量,频率,变声,当然设置方法都差不多,都是先拿到它对应功能的值然后在进行加减。下载pyttsx3模块pip install pyttsx3调用import pyttsx3 # 初始化 engine = pyttsx3.init(); # 设置个性化参数 engine.setProperty('rate',150) #调整语速 engine.setProperty('volume',2.0) #调整音量 voices = engine.getProperty('voices'); engine.setProperty('voice',voices[0].id); mp3_save_path = "./test.mp3" text="西游记" # 使用引擎进行渲染,亲测不能省略这一步,省略了就保存的文件为空 engine.say(text); engine.runAndWait(); #播放音频 # 保存到文件 engine.save_to_file(text,mp3_save_path);2.gtts模快(亲测没跑通)安装pip install gtts使用from gtts import gTTS mp3_save_path = "./test.mp3" text="西游记" # text:音频内容 # lang: 音频语言 tts = gTTS(text=text, lang='zh-tw') tts.save(mp3_save_path)
2023年05月09日
303 阅读
0 评论
0 点赞
2022-12-04
代码绘制爱心
代码绘制爱心0.背景最近看到一个剧叫点燃我温暖你,剧中大一的学生用c++绘制了普通的和很炫酷的爱心,女朋友还蛮有兴趣的,今天有空了准备也来试试复现一下。2.绘制静态爱心2.0 相关知识爱心的绘制主要运用到的几何知识是笛卡尔的心形线,心形线的极坐标下的函数表达式为:$$ r=a(1-sinθ) $$其中a是一个a>0的系数,可以任意取正值,它决定心形的大小。转为直角坐标系下的函数表达式为:$$ x^2+y^2=a\sqrt{x^2+y^2} - ay $$然后经过了一通平移等操作,最后绘制用得心形线条曲线的方程为:$$ (x^2+y^2-1)^3-x^3y^3=0 $$2.1 代码#include<iostream> #include<windows.h> #include<cmath> using namespace std; int main() { float x, y, a; for (y = 1.5f; y > -1.5f; y -= 0.1f) { for (x = -1.5f; x < 1.5f; x += 0.05f) { // 逐行绘制爱心的每一行 float fx = pow(x*x+y*y-1,3)- pow(x,2)*pow(y,3); if(fx <= 0.0f) { cout<<'*'; } else { cout<<' '; } } cout<<endl; } system("pause"); return 0; }2.2 效果图3.绘制跳动的爱心3.0 原理github拷贝过来的,原理还在解读中,先码住。3.1 代码heart.pyfrom math import cos, pi import numpy as np import cv2 import os, glob class HeartSignal: def __init__(self, curve="heart", title="Love U", frame_num=20, seed_points_num=2000, seed_num=None, highlight_rate=0.3, background_img_dir="", set_bg_imgs=False, bg_img_scale=0.2, bg_weight=0.3, curve_weight=0.7, frame_width=1080, frame_height=960, scale=10.1, base_color=None, highlight_points_color_1=None, highlight_points_color_2=None, wait=100, n_star=5, m_star=2): super().__init__() self.curve = curve self.title = title self.highlight_points_color_2 = highlight_points_color_2 self.highlight_points_color_1 = highlight_points_color_1 self.highlight_rate = highlight_rate self.base_color = base_color self.n_star = n_star self.m_star = m_star self.curve_weight = curve_weight img_paths = glob.glob(background_img_dir + "/*") self.bg_imgs = [] self.set_bg_imgs = set_bg_imgs self.bg_weight = bg_weight if os.path.exists(background_img_dir) and len(img_paths) > 0 and set_bg_imgs: for img_path in img_paths: img = cv2.imread(img_path) self.bg_imgs.append(img) first_bg = self.bg_imgs[0] width = int(first_bg.shape[1] * bg_img_scale) height = int(first_bg.shape[0] * bg_img_scale) first_bg = cv2.resize(first_bg, (width, height), interpolation=cv2.INTER_AREA) # 对齐图片,自动裁切中间 new_bg_imgs = [first_bg, ] for img in self.bg_imgs[1:]: width_close = abs(first_bg.shape[1] - img.shape[1]) < abs(first_bg.shape[0] - img.shape[0]) if width_close: # resize height = int(first_bg.shape[1] / img.shape[1] * img.shape[0]) width = first_bg.shape[1] img = cv2.resize(img, (width, height), interpolation=cv2.INTER_AREA) # crop and fill if img.shape[0] > first_bg.shape[0]: crop_num = img.shape[0] - first_bg.shape[0] crop_top = crop_num // 2 crop_bottom = crop_num - crop_top img = np.delete(img, range(crop_top), axis=0) img = np.delete(img, range(img.shape[0] - crop_bottom, img.shape[0]), axis=0) elif img.shape[0] < first_bg.shape[0]: fill_num = first_bg.shape[0] - img.shape[0] fill_top = fill_num // 2 fill_bottom = fill_num - fill_top img = np.concatenate([np.zeros([fill_top, width, 3]), img, np.zeros([fill_bottom, width, 3])], axis=0) else: width = int(first_bg.shape[0] / img.shape[0] * img.shape[1]) height = first_bg.shape[0] img = cv2.resize(img, (width, height), interpolation=cv2.INTER_AREA) # crop and fill if img.shape[1] > first_bg.shape[1]: crop_num = img.shape[1] - first_bg.shape[1] crop_top = crop_num // 2 crop_bottom = crop_num - crop_top img = np.delete(img, range(crop_top), axis=1) img = np.delete(img, range(img.shape[1] - crop_bottom, img.shape[1]), axis=1) elif img.shape[1] < first_bg.shape[1]: fill_num = first_bg.shape[1] - img.shape[1] fill_top = fill_num // 2 fill_bottom = fill_num - fill_top img = np.concatenate([np.zeros([fill_top, width, 3]), img, np.zeros([fill_bottom, width, 3])], axis=1) new_bg_imgs.append(img) self.bg_imgs = new_bg_imgs assert all(img.shape[0] == first_bg.shape[0] and img.shape[1] == first_bg.shape[1] for img in self.bg_imgs), "背景图片宽和高不一致" self.frame_width = self.bg_imgs[0].shape[1] self.frame_height = self.bg_imgs[0].shape[0] else: self.frame_width = frame_width # 窗口宽度 self.frame_height = frame_height # 窗口高度 self.center_x = self.frame_width / 2 self.center_y = self.frame_height / 2 self.main_curve_width = -1 self.main_curve_height = -1 self.frame_points = [] # 每帧动态点坐标 self.frame_num = frame_num # 帧数 self.seed_num = seed_num # 伪随机种子,设置以后除光晕外粒子相对位置不动(减少内部闪烁感) self.seed_points_num = seed_points_num # 主图粒子数 self.scale = scale # 缩放比例 self.wait = wait def curve_function(self, curve): curve_dict = { "heart": self.heart_function, "butterfly": self.butterfly_function, "star": self.star_function, } return curve_dict[curve] def heart_function(self, t, frame_idx=0, scale=5.20): """ 图形方程 :param frame_idx: 帧的索引,根据帧数变换心形 :param scale: 放大比例 :param t: 参数 :return: 坐标 """ trans = 3 - (1 + self.periodic_func(frame_idx, self.frame_num)) * 0.5 # 改变心形饱满度度的参数 x = 15 * (np.sin(t) ** 3) t = np.where((pi < t) & (t < 2 * pi), 2 * pi - t, t) # 翻转x > 0部分的图形到3、4象限 y = -(14 * np.cos(t) - 4 * np.cos(2 * t) - 2 * np.cos(3 * t) - np.cos(trans * t)) ign_area = 0.15 center_ids = np.where((x > -ign_area) & (x < ign_area)) if np.random.random() > 0.32: x, y = np.delete(x, center_ids), np.delete(y, center_ids) # 删除稠密部分的扩散,为了美观 # 放大 x *= scale y *= scale # 移到画布中央 x += self.center_x y += self.center_y # 原心形方程 # x = 15 * (sin(t) ** 3) # y = -(14 * cos(t) - 4 * cos(2 * t) - 2 * cos(3 * t) - cos(3 * t)) return x.astype(int), y.astype(int) def butterfly_function(self, t, frame_idx=0, scale=5.2): """ 图形函数 :param frame_idx: :param scale: 放大比例 :param t: 参数 :return: 坐标 """ # 基础函数 # t = t * pi p = np.exp(np.sin(t)) - 2.5 * np.cos(4 * t) + np.sin(t) ** 5 x = 5 * p * np.cos(t) y = - 5 * p * np.sin(t) # 放大 x *= scale y *= scale # 移到画布中央 x += self.center_x y += self.center_y return x.astype(int), y.astype(int) def star_function(self, t, frame_idx=0, scale=5.2): n = self.n_star / self.m_star p = np.cos(pi / n) / np.cos(pi / n - (t % (2 * pi / n))) x = 15 * p * np.cos(t) y = 15 * p * np.sin(t) # 放大 x *= scale y *= scale # 移到画布中央 x += self.center_x y += self.center_y return x.astype(int), y.astype(int) def shrink(self, x, y, ratio, offset=1, p=0.5, dist_func="uniform"): """ 带随机位移的抖动 :param x: 原x :param y: 原y :param ratio: 缩放比例 :param p: :param offset: :return: 转换后的x,y坐标 """ x_ = (x - self.center_x) y_ = (y - self.center_y) force = 1 / ((x_ ** 2 + y_ ** 2) ** p + 1e-30) dx = ratio * force * x_ dy = ratio * force * y_ def d_offset(x): if dist_func == "uniform": return x + np.random.uniform(-offset, offset, size=x.shape) elif dist_func == "norm": return x + offset * np.random.normal(0, 1, size=x.shape) dx, dy = d_offset(dx), d_offset(dy) return x - dx, y - dy def scatter(self, x, y, alpha=0.75, beta=0.15): """ 随机内部扩散的坐标变换 :param alpha: 扩散因子 - 松散 :param x: 原x :param y: 原y :param beta: 扩散因子 - 距离 :return: x,y 新坐标 """ ratio_x = - beta * np.log(np.random.random(x.shape) * alpha) ratio_y = - beta * np.log(np.random.random(y.shape) * alpha) dx = ratio_x * (x - self.center_x) dy = ratio_y * (y - self.center_y) return x - dx, y - dy def periodic_func(self, x, x_num): """ 跳动周期曲线 :param p: 参数 :return: y """ # 可以尝试换其他的动态函数,达到更有力量的效果(贝塞尔?) def ori_func(t): return cos(t) func_period = 2 * pi return ori_func(x / x_num * func_period) def gen_points(self, points_num, frame_idx, shape_func): # 用周期函数计算得到一个因子,用到所有组成部件上,使得各个部分的变化周期一致 cy = self.periodic_func(frame_idx, self.frame_num) ratio = 10 * cy # 图形 period = 2 * pi * self.m_star if self.curve == "star" else 2 * pi seed_points = np.linspace(0, period, points_num) seed_x, seed_y = shape_func(seed_points, frame_idx, scale=self.scale) x, y = self.shrink(seed_x, seed_y, ratio, offset=2) curve_width, curve_height = int(x.max() - x.min()), int(y.max() - y.min()) self.main_curve_width = max(self.main_curve_width, curve_width) self.main_curve_height = max(self.main_curve_height, curve_height) point_size = np.random.choice([1, 2], x.shape, replace=True, p=[0.5, 0.5]) tag = np.ones_like(x) def delete_points(x_, y_, ign_area, ign_prop): ign_area = ign_area center_ids = np.where((x_ > self.center_x - ign_area) & (x_ < self.center_x + ign_area)) center_ids = center_ids[0] np.random.shuffle(center_ids) del_num = round(len(center_ids) * ign_prop) del_ids = center_ids[:del_num] x_, y_ = np.delete(x_, del_ids), np.delete(y_, del_ids) # 删除稠密部分的扩散,为了美观 return x_, y_ # 多层次扩散 for idx, beta in enumerate(np.linspace(0.05, 0.2, 6)): alpha = 1 - beta x_, y_ = self.scatter(seed_x, seed_y, alpha, beta) x_, y_ = self.shrink(x_, y_, ratio, offset=round(beta * 15)) x = np.concatenate((x, x_), 0) y = np.concatenate((y, y_), 0) p_size = np.random.choice([1, 2], x_.shape, replace=True, p=[0.55 + beta, 0.45 - beta]) point_size = np.concatenate((point_size, p_size), 0) tag_ = np.ones_like(x_) * 2 tag = np.concatenate((tag, tag_), 0) # 光晕 halo_ratio = int(7 + 2 * abs(cy)) # 收缩比例随周期变化 # 基础光晕 x_, y_ = shape_func(seed_points, frame_idx, scale=self.scale + 0.9) x_1, y_1 = self.shrink(x_, y_, halo_ratio, offset=18, dist_func="uniform") x_1, y_1 = delete_points(x_1, y_1, 20, 0.5) x = np.concatenate((x, x_1), 0) y = np.concatenate((y, y_1), 0) # 炸裂感光晕 halo_number = int(points_num * 0.6 + points_num * abs(cy)) # 光晕点数也周期变化 seed_points = np.random.uniform(0, 2 * pi, halo_number) x_, y_ = shape_func(seed_points, frame_idx, scale=self.scale + 0.9) x_2, y_2 = self.shrink(x_, y_, halo_ratio, offset=int(6 + 15 * abs(cy)), dist_func="norm") x_2, y_2 = delete_points(x_2, y_2, 20, 0.5) x = np.concatenate((x, x_2), 0) y = np.concatenate((y, y_2), 0) # 膨胀光晕 x_3, y_3 = shape_func(np.linspace(0, 2 * pi, int(points_num * .4)), frame_idx, scale=self.scale + 0.2) x_3, y_3 = self.shrink(x_3, y_3, ratio * 2, offset=6) x = np.concatenate((x, x_3), 0) y = np.concatenate((y, y_3), 0) halo_len = x_1.shape[0] + x_2.shape[0] + x_3.shape[0] p_size = np.random.choice([1, 2, 3], halo_len, replace=True, p=[0.7, 0.2, 0.1]) point_size = np.concatenate((point_size, p_size), 0) tag_ = np.ones(halo_len) * 2 * 3 tag = np.concatenate((tag, tag_), 0) x_y = np.around(np.stack([x, y], axis=1), 0) x, y = x_y[:, 0], x_y[:, 1] return x, y, point_size, tag def get_frames(self, shape_func): for frame_idx in range(self.frame_num): np.random.seed(self.seed_num) self.frame_points.append(self.gen_points(self.seed_points_num, frame_idx, shape_func)) frames = [] def add_points(frame, x, y, size, tag): highlight1 = np.array(self.highlight_points_color_1, dtype='uint8') highlight2 = np.array(self.highlight_points_color_2, dtype='uint8') base_col = np.array(self.base_color, dtype='uint8') x, y = x.astype(int), y.astype(int) frame[y, x] = base_col size_2 = np.int64(size == 2) frame[y, x + size_2] = base_col frame[y + size_2, x] = base_col size_3 = np.int64(size == 3) frame[y + size_3, x] = base_col frame[y - size_3, x] = base_col frame[y, x + size_3] = base_col frame[y, x - size_3] = base_col frame[y + size_3, x + size_3] = base_col frame[y - size_3, x - size_3] = base_col # frame[y - size_3, x + size_3] = color # frame[y + size_3, x - size_3] = color # 高光 random_sample = np.random.choice([1, 0], size=tag.shape, p=[self.highlight_rate, 1 - self.highlight_rate]) # tag2_size1 = np.int64((tag <= 2) & (size == 1) & (random_sample == 1)) # frame[y * tag2_size1, x * tag2_size1] = highlight2 tag2_size2 = np.int64((tag <= 2) & (size == 2) & (random_sample == 1)) frame[y * tag2_size2, x * tag2_size2] = highlight1 # frame[y * tag2_size2, (x + 1) * tag2_size2] = highlight2 # frame[(y + 1) * tag2_size2, x * tag2_size2] = highlight2 frame[(y + 1) * tag2_size2, (x + 1) * tag2_size2] = highlight2 for x, y, size, tag in self.frame_points: frame = np.zeros([self.frame_height, self.frame_width, 3], dtype="uint8") add_points(frame, x, y, size, tag) frames.append(frame) return frames def draw(self, times=10): frames = self.get_frames(self.curve_function(self.curve)) for i in range(times): for frame in frames: frame = cv2.cvtColor(frame, cv2.COLOR_RGB2BGR) if len(self.bg_imgs) > 0 and self.set_bg_imgs: frame = cv2.addWeighted(self.bg_imgs[i % len(self.bg_imgs)], self.bg_weight, frame, self.curve_weight, 0) cv2.imshow(self.title, frame) cv2.waitKey(self.wait) if __name__ == '__main__': import yaml settings = yaml.load(open("./settings.yaml", "r", encoding="utf-8"), Loader=yaml.FullLoader) if settings["wait"] == -1: settings["wait"] = int(settings["period_time"] / settings["frame_num"]) del settings["period_time"] times = settings["times"] del settings["times"] heart = HeartSignal(seed_num=5201314, **settings) heart.draw(times)settings.yaml# 颜色:RGB三原色数值 0~255 # 设置高光时,尽量选择接近主色的颜色,看起来会和谐一点 # 视频里的蓝色调 #base_color: # 主色 默认玫瑰粉 # - 30 # - 100 # - 100 #highlight_points_color_1: # 高光粒子色1 默认淡紫色 # - 150 # - 120 # - 220 #highlight_points_color_2: # 高光粒子色2 默认淡粉色 # - 128 # - 140 # - 140 base_color: # 主色 默认玫瑰粉 - 228 - 100 - 100 highlight_points_color_1: # 高光粒子色1 默认淡紫色 - 180 - 87 - 200 highlight_points_color_2: # 高光粒子色2 默认淡粉色 - 228 - 140 - 140 period_time: 1000 * 2 # 周期时间,默认1.5s一个周期 times: 50 # 播放周期数,一个周期跳动1次 frame_num: 24 # 一个周期的生成帧数 wait: 60 # 每一帧停留时间, 设置太短可能造成闪屏,设置 -1 自动设置为 period_time / frame_num seed_points_num: 2000 # 构成主图的种子粒子数,总粒子数是这个的8倍左右(包括散点和光晕) highlight_rate: 0.2 # 高光粒子的比例 frame_width: 720 # 窗口宽度,单位像素,设置背景图片后失效 frame_height: 640 # 窗口高度,单位像素,设置背景图片后失效 scale: 9.1 # 主图缩放比例 curve: "heart" # 图案类型:heart, butterfly, star n_star: 7 # n-角型/星,如果curve设置成star才会生效,五角星:n-star:5, m-star:2 m_star: 3 # curve设置成star才会生效,n-角形 m-star都是1,n-角星 m-star大于1,比如 七角星:n-star:7, m-star:2 或 3 title: "Love Li Xun" # 仅支持字母,中文乱码 background_img_dir: "src/center_imgs" # 这个目录放置背景图片,建议像素在400 X 400以上,否则可能报错,如果图片实在小,可以调整上面scale把爱心缩小 set_bg_imgs: false # true或false,设置false用默认黑背景 bg_img_scale: 0.6 # 0 - 1,背景图片缩放比例 bg_weight: 0.4 # 0 - 1,背景图片权重,可看做透明度吧 curve_weight: 1 # 同上 # ======================== 推荐参数: 直接复制数值替换上面对应参数 ================================== # 蝴蝶,报错很可能是蝴蝶缩放大小超出窗口宽和高 # curve: "butterfly" # frame_width: 800 # frame_height: 720 # scale: 60 # base_color: [100, 100, 228] # highlight_points_color_1: [180, 87, 200] # highlight_points_color_2: [228, 140, 140]3.2 运行效果参考资料爱心函数https://github.com/131250208/FunnyToys/blob/main/heart.py
2022年12月04日
460 阅读
0 评论
0 点赞
2022-08-31
Selenium:Python爬虫进阶
1.简介1.1 什么是Selenium?官网: Selenium是一个用于Web应用程序测试的工具。真实:大量用于网络爬虫,相比requests爬虫,完全模拟真人使用浏览器的流程,对于动态JS加载的网页更容易爬取1.2 Selenium的功能框架底层使用JavaScript模拟真实用户对浏览器进行操作。测试脚本执行时,浏览器自动按照脚本代码做出点击,输入,打开,验证等操作,就像真实用户所做的一样,从终端用户的角度测试应用程序。可用于较难的爬虫:动态JS加载、登录验证、表单提交等使用简单,可使用Python、Java等多种语言编写用例脚本。1.3 为什么要学习Selenium?requests爬虫局限性较大,分析困难、被封禁概率高可用于较难的爬虫伪装成真实的浏览器,被封禁的概率更低动态JS加载登录验证表单提交等1.4 Selenium的缺点相比requests,性能比较差,爬取的慢1.5 Selenium运行框架2.Selenium环境搭建1.电脑安装谷歌Chrome浏览器(其他浏览器不推荐)需要看一下当前的Chrome版本号,下载对应ChromeDriver2.下载安装 ChromeDriverhttps://www.selenium.dev/documentation/getting_started/installing_browser_drivers/windowns 放到C:\WebDriver\bin目录,这个目录加入系统PATH3.Python安装selenium库pip install selenium3.Selenium实战案例3.1 爬取电影天堂的视频真实下载地址用到selenium加载页面渲染出m3u8文件的地址from selenium import webdriver from selenium.webdriver.chrome.options import Options from selenium.webdriver.chrome.service import Service from selenium.webdriver.common.by import By from selenium.webdriver.support.wait import WebDriverWait from bs4 import BeautifulSoup import re # 实例化一个浏览器对象(传入浏览器的驱动程序) 通过Options实现无可视化界面的操作 chrome_options = Options() chrome_options.add_argument('--headless') # 不显示浏览器在后台运行 chrome_service = Service("chromedriver.exe"); browser = webdriver.Chrome(service=chrome_service,options=chrome_options) # 封装通过selenium获取html的方法 def get_html_by_selenium(url): # 对url发起请求 browser.get(url) # 等待页面加载完成 wait = WebDriverWait(browser, 3); # 获取页面源代码 page_html = browser.page_source return page_html # 电视剧页面地址_base base_url = "https://www.dy10000.com/wplay/68599-2-{}.html" # 生成下载脚本 for i in range(42,48): url = base_url.format(i) html = get_html_by_selenium(url) soup = BeautifulSoup(html, features='lxml') script_all = soup.body.find_all("script") for script in script_all: m3u8_search = re.search(r"http.*?m3u8", str(script)) if m3u8_search: url_m3u8 = m3u8_search.group(0).replace("\\", "") print("ffmpeg -i ", url_m3u8, " -c copy -bsf:a aac_adtstoasc " + str(i) + ".mp4") break # 退出浏览器 browser.quit()ffmpeg -i https://new.iskcd.com/20220518/FhKxDhXk/index.m3u8 -c copy -bsf:a aac_adtstoasc 42.mp4 ffmpeg -i https://new.iskcd.com/20220518/2MSrEhUz/index.m3u8 -c copy -bsf:a aac_adtstoasc 43.mp4 ffmpeg -i https://new.iskcd.com/20220519/7o5nJxJ3/index.m3u8 -c copy -bsf:a aac_adtstoasc 44.mp4 ffmpeg -i https://new.iskcd.com/20220519/BB2x9BaG/index.m3u8 -c copy -bsf:a aac_adtstoasc 45.mp4 ffmpeg -i https://new.iskcd.com/20220520/AxB2XF4T/index.m3u8 -c copy -bsf:a aac_adtstoasc 46.mp43.2 爬取电影先生的视频真实下载地址用到selenium加载页面渲染出m3u8文件的地址from selenium import webdriver from selenium.webdriver.chrome.options import Options from selenium.webdriver.chrome.service import Service from selenium.webdriver.common.by import By from selenium.webdriver.support.wait import WebDriverWait from bs4 import BeautifulSoup import re # 实例化一个浏览器对象(传入浏览器的驱动程序) 通过Options实现无可视化界面的操作 chrome_options = Options() chrome_options.add_argument('--headless') # 不显示浏览器在后台运行 chrome_service = Service("chromedriver.exe"); browser = webdriver.Chrome(service=chrome_service,options=chrome_options) # 封装通过selenium获取html的方法 def get_html_by_selenium(url): # 对url发起请求 browser.get(url) # 等待页面加载完成 wait = WebDriverWait(browser, 5); # 获取页面源代码 page_html = browser.page_source return page_html # 电视剧页面地址_base base_url = "https://dyxs15.com/paly-222156-5-{}/" # 生成下载脚本 for i in range(15,41): url = base_url.format(i) html = get_html_by_selenium(url) soup = BeautifulSoup(html, features='lxml') td_all = soup.body.find_all("td") for td in td_all: m3u8_search = re.search(r"http.*?m3u8", str(td)) if m3u8_search: url_m3u8 = m3u8_search.group(0).replace("\\", "") print("ffmpeg -i ", url_m3u8, " -c copy -bsf:a aac_adtstoasc " + str(i) + ".mp4") break break # 退出浏览器 browser.quit()ffmpeg -i https://new.qqaku.com/20220526/t5C1cVna/index.m3u8 -c copy -bsf:a aac_adtstoasc 15.mp4 ······ ffmpeg -i https://new.qqaku.com/20220617/Wpf7uowm/index.m3u8 -c copy -bsf:a aac_adtstoasc 40.mp4参考资料https://www.bilibili.com/video/BV1WF411z7qB自动化爬虫selenium基础教程selenium如何不显示浏览器在后台运行Python selenium的这三种等待方式一定要会!
2022年08月31日
850 阅读
0 评论
0 点赞
2022-06-10
leetcode|中等:剑指 Offer 35. 复杂链表的复制
1.题目请实现 copyRandomList 函数,复制一个复杂链表。在复杂链表中,每个节点除了有一个 next 指针指向下一个节点,还有一个 random 指针指向链表中的任意节点或者 null。示例 1:输入:head = [[7,null],[13,0],[11,4],[10,2],[1,0]] 输出:[[7,null],[13,0],[11,4],[10,2],[1,0]]示例 2:输入:head = [[1,1],[2,1]] 输出:[[1,1],[2,1]]示例 3:输入:head = [[3,null],[3,0],[3,null]] 输出:[[3,null],[3,0],[3,null]]示例 4:输入:head = [] 输出:[] 解释:给定的链表为空(空指针),因此返回 null。提示:-10000 <= Node.val <= 10000Node.random 为空(null)或指向链表中的节点。节点数目不超过 1000 。2. 题解2.1 思路分析思路1:哈希表法 利用哈希表的查询特点,考虑构建 原链表节点 和 新链表对应节点 的键值对映射关系,再遍历构建新链表各节点的 next 和 random 引用指向即可。2.2 代码实现思路1:哈希表法/* // Definition for a Node. class Node { int val; Node next; Node random; public Node(int val) { this.val = val; this.next = null; this.random = null; } } */ class Solution { public Node copyRandomList(Node head) { if(head == null) return null; Node cur = head; // 保存头节点,用于遍历链表 Map<Node,Node> map = new HashMap<Node,Node>();//用于保存新旧节点之间的关系 // 复制各节点,并建立 “原节点 -> 新节点” 的 Map 映射 while (cur!=null){ map.put(cur,new Node(cur.val)); cur = cur.next; } // 补全next和random的映射关系 cur = head; while (cur!=null){ map.get(cur).next = map.get(cur.next); map.get(cur).random = map.get(cur.random); cur = cur.next; } return map.get(head); } }2.3 提交结果提交结果执行用时内存消耗语言提交时间备注通过0 ms41 MBJava2022/06/10 15:18添加备注参考资料https://leetcode.cn/problems/fu-za-lian-biao-de-fu-zhi-lcof
2022年06月10日
649 阅读
0 评论
0 点赞
2022-06-10
leetcode|简单:剑指 Offer 24. 反转链表
1.题目定义一个函数,输入一个链表的头节点,反转该链表并输出反转后链表的头节点。示例:输入: 1->2->3->4->5->NULL 输出: 5->4->3->2->1->NULL限制:0 <= 节点个数 <= 50002. 题解2.1 思路分析思路1: 本题比较简单直接上代码2.2 代码实现思路1/** * Definition for singly-linked list. * public class ListNode { * int val; * ListNode next; * ListNode(int x) { val = x; } * } */ class Solution { public ListNode reverseList(ListNode head) { if(head==null || head.next==null){ return head; } ListNode newHead = head.next; ListNode nextNewHead = newHead.next; head.next = null; while (nextNewHead!=null){ newHead.next = head; head = newHead; newHead = nextNewHead; nextNewHead = nextNewHead.next; } newHead.next = head; return newHead; } }思路1优化/** * Definition for singly-linked list. * public class ListNode { * int val; * ListNode next; * ListNode(int x) { val = x; } * } */ class Solution { public ListNode reverseList(ListNode head) { ListNode pre = null,cur=head; while (cur!=null){ ListNode tmp = cur.next; cur.next=pre; pre=cur; cur = tmp; } return pre; } }2.3 提交结果提交结果执行用时内存消耗语言提交时间备注通过0 ms41 MBJava2022/06/10 11:15添加备注提交结果执行用时内存消耗语言提交时间备注通过0 ms40.8 MBJava2022/06/10 11:32添加备注参考资料https://leetcode.cn/problems/fan-zhuan-lian-biao-lcof
2022年06月10日
590 阅读
0 评论
0 点赞
2022-06-10
leetcode|简单:剑指 Offer 06. 从尾到头打印链表
1.题目输入一个链表的头节点,从尾到头反过来返回每个节点的值(用数组返回)。示例 1:输入:head = [1,3,2] 输出:[2,3,1]限制:0 <= 链表长度 <= 100002. 题解2.1 思路分析统计链表长度申请数组并逐一填入链表元素反转数组2.2 代码实现/** * Definition for singly-linked list. * public class ListNode { * int val; * ListNode next; * ListNode(int x) { val = x; } * } */ class Solution { public int[] reversePrint(ListNode head) { // 1.统计链表长度 int listLen = 0; ListNode tmp = head; while (tmp!=null){ listLen++; tmp = tmp.next; } // 2.申请数组并逐一填入链表元素 int[] res = new int[listLen]; tmp = head; int resIndex=0; while (tmp!=null){ res[resIndex++] = tmp.val; tmp = tmp.next; } // 3.反转数组 for (int i = 0; i < listLen/2; i++) { int tmpItem = res[i]; res[i] = res[listLen-1-i]; res[listLen-1-i] = tmpItem; } return res; } }2.3 提交结果提交结果执行用时内存消耗语言提交时间备注通过0 ms42.1 MBJava2022/06/10 10:30添加备注参考资料https://leetcode.cn/problems/cong-wei-dao-tou-da-yin-lian-biao-lcof
2022年06月10日
487 阅读
0 评论
0 点赞
2022-06-10
leetcode|简单:剑指 Offer 09. 用两个栈实现队列
1.题目用两个栈实现一个队列。队列的声明如下,请实现它的两个函数 appendTail 和 deleteHead ,分别完成在队列尾部插入整数和在队列头部删除整数的功能。(若队列中没有元素,deleteHead 操作返回 -1 )示例 1:输入: ["CQueue","appendTail","deleteHead","deleteHead"] [[],[3],[],[]] 输出:[null,null,3,-1]示例 2:输入: ["CQueue","deleteHead","appendTail","appendTail","deleteHead","deleteHead"] [[],[],[5],[2],[],[]] 输出:[null,-1,null,null,5,2]提示:1 <= values <= 10000最多会对 appendTail、deleteHead 进行 10000 次调用2. 题解2.1 思路分析栈无法实现队列功能: 栈底元素(对应队首元素)无法直接删除,需要将上方所有元素出栈。双栈可实现列表倒序: 设有含三个元素的栈 A\=[1,2,3]和空栈 B\=[]。若循环执行 A元素出栈并添加入栈 B ,直到栈 A为空,则 A\=[], B\=[3,2,1],即 栈 B 元素实现栈 A 元素倒序 。利用栈 B 删除队首元素: 倒序后,B 执行出栈则相当于删除了 A 的栈底元素,即对应队首元素。可以设计栈 A 用于加入队尾操作,栈 B 用于将元素倒序,从而实现删除队首元素。加入队尾 appendTail()函数: 将数字 val 加入栈 A 即可。删除队首deleteHead()函数: 有以下三种情况。当栈 B 不为空: B中仍有已完成倒序的元素,因此直接返回 B 的栈顶元素。否则,当 A 为空: 即两个栈都为空,无元素,因此返回 −1。否则: 将栈 A 元素全部转移至栈 B 中,实现元素倒序,并返回栈 B 的栈顶元素。2.2 代码实现思路1:class CQueue { Stack<Integer> A,B; public CQueue() { A = new Stack<Integer>(); B = new Stack<Integer>(); } public void appendTail(int value) { A.push(value); } public int deleteHead() { if(!B.empty()){ return B.pop(); }else if(A.empty()){ return -1; }else { // 把栈B中的元素全部倒序移入栈A while (!A.empty()){ B.push(A.pop()); } return B.pop(); } } } /** * Your CQueue object will be instantiated and called as such: * CQueue obj = new CQueue(); * obj.appendTail(value); * int param_2 = obj.deleteHead(); */2.3 提交结果提交结果执行用时内存消耗语言提交时间备注通过72 ms47.8 MBJava2022/06/09 10:30添加备注参考资料https://leetcode.cn/problems/yong-liang-ge-zhan-shi-xian-dui-lie-lcofhttps://leetcode.cn/problems/yong-liang-ge-zhan-shi-xian-dui-lie-lcof/solution/mian-shi-ti-09-yong-liang-ge-zhan-shi-xian-dui-l-2/
2022年06月10日
531 阅读
0 评论
0 点赞
2022-06-09
leetcode|简单:剑指 Offer 30. 包含min函数的栈
1.题目定义栈的数据结构,请在该类型中实现一个能够得到栈的最小元素的 min 函数在该栈中,调用 min、push 及 pop 的时间复杂度都是 O(1)。示例: MinStack minStack = new MinStack(); minStack.push(-2); minStack.push(0); minStack.push(-3); minStack.min(); --> 返回 -3. minStack.pop(); minStack.top(); --> 返回 0. minStack.min(); --> 返回 -2.提示:各函数的调用总次数不超过 20000 次2. 题解2.1 思路分析思路1: 使用辅助栈来维护最小值 只需要对现有的栈功能添加一个用于维护最小值的辅助栈minStack(普通栈) 每次push的时候都往minStack中push当前的最小值(由minStack.peek()和待push元素x得出) 每次pop的时候minStack也执行相应的pop 则每次调用min的时候只需要返回minStack.peek()即可2.2 代码实现思路1:使用辅助栈来维护最小值import java.util.Stack; class MinStack { Stack<Integer> stack; Stack<Integer> minStack; /** initialize your data structure here. */ public MinStack() { stack = new Stack<Integer>(); minStack = new Stack<Integer>(); } public void push(int x) { // push更新min if(minStack.empty()) { minStack.push(x); }else { int min = minStack.peek()<x?minStack.peek():x; minStack.push(min); } stack.push(x); } public void pop() { // pop更新min minStack.pop(); stack.pop(); } public int top() { return stack.peek(); } public int min() { return minStack.peek(); } } /** * Your MinStack object will be instantiated and called as such: * MinStack obj = new MinStack(); * obj.push(x); * obj.pop(); * int param_3 = obj.top(); * int param_4 = obj.min(); */2.3 提交结果提交结果执行用时内存消耗语言提交时间备注通过14 ms43.4 MBJava2022/06/09 10:54添加备注参考资料https://leetcode.cn/problems/bao-han-minhan-shu-de-zhan-lcof
2022年06月09日
613 阅读
0 评论
0 点赞
2022-06-08
leetcode|困难:4. 寻找两个正序数组的中位数
1.题目给定两个大小分别为 m 和 n 的正序(从小到大)数组 nums1 和 nums2。请你找出并返回这两个正序数组的 中位数 。算法的时间复杂度应该为 O(log (m+n)) 。示例 1:输入:nums1 = [1,3], nums2 = [2] 输出:2.00000 解释:合并数组 = [1,2,3] ,中位数 2示例 2:输入:nums1 = [1,2], nums2 = [3,4] 输出:2.50000 解释:合并数组 = [1,2,3,4] ,中位数 (2 + 3) / 2 = 2.5提示:nums1.length == mnums2.length == n0 <= m <= 10000 <= n <= 10001 <= m + n <= 2000$-10^6$ <= nums1[i], nums2[i] <= $10^6$2. 题解2.1 思路分析思路1: 确定中位数的组成部分midLeft和midRight,总数为奇数的midLeft=midRight 通过利用寻找第k小的数的算法来锁定midLeft和midRight寻找第k小的数算法由于数列是有序的,其实我们完全可以一半儿一半儿的排除。假设我们要找第 k 小数,我们可以每次循环排除掉 k/2 个数。看下边一个例子。假设我们要找第 7 小的数字。我们比较两个数组的第 k/2 个数字,如果 k 是奇数,向下取整。也就是比较第 3 个数字,上边数组中的 4 和下边数组中的 3,如果哪个小,就表明该数组的前 k/2 个数字都不是第 k 小数字,所以可以排除。也就是 1,2,3 这三个数字不可能是第 7 小的数字,我们可以把它排除掉。将 1349和 45678910 两个数组作为新的数组进行比较。更一般的情况 A[1] ,A[2] ,A[3],A[k/2] ... ,B[1],B[2],B[3],B[k/2] ... ,如果 A[k/2]<B[k/2] ,那么A[1],A[2],A[3],A[k/2]都不可能是第 k 小的数字。A 数组中比 A[k/2] 小的数有 k/2-1 个,B 数组中,B[k/2] 比 A[k/2] 小,假设 B[k/2] 前边的数字都比 A[k/2] 小,也只有 k/2-1 个,所以比 A[k/2] 小的数字最多有 k/1-1+k/2-1=k-2个,所以 A[k/2] 最多是第 k-1 小的数。而比 A[k/2] 小的数更不可能是第 k 小的数了,所以可以把它们排除。橙色的部分表示已经去掉的数字。由于我们已经排除掉了 3 个数字,就是这 3 个数字一定在最前边,所以在两个新数组中,我们只需要找第 7 - 3 = 4 小的数字就可以了,也就是 k = 4。此时两个数组,比较第 2 个数字,3 < 5,所以我们可以把小的那个数组中的 1 ,3 排除掉了。我们又排除掉 2 个数字,所以现在找第 4 - 2 = 2 小的数字就可以了。此时比较两个数组中的第 k / 2 = 1 个数,4 == 4,怎么办呢?由于两个数相等,所以我们无论去掉哪个数组中的都行,因为去掉 1 个总会保留 1 个的,所以没有影响。为了统一,我们就假设 4 > 4 吧,所以此时将下边的 4 去掉。由于又去掉 1 个数字,此时我们要找第 1 小的数字,所以只需判断两个数组中第一个数字哪个小就可以了,也就是 4。所以第 7 小的数字是 4。我们每次都是取 k/2 的数进行比较,有时候可能会遇到数组长度小于 k/2的时候。此时 k / 2 等于 3,而上边的数组长度是 2,我们此时将箭头指向它的末尾就可以了。这样的话,由于 2 < 3,所以就会导致上边的数组 1,2 都被排除。造成下边的情况。由于 2 个元素被排除,所以此时 k = 5,又由于上边的数组已经空了,我们只需要返回下边的数组的第 5 个数字就可以了。从上边可以看到,无论是找第奇数个还是第偶数个数字,对我们的算法并没有影响,而且在算法进行中,k 的值都有可能从奇数变为偶数,最终都会变为 1 或者由于一个数组空了,直接返回结果。所以我们采用递归的思路,为了防止数组长度小于 k/2,所以每次比较 min(k/2,len(数组) 对应的数字,把小的那个对应的数组的数字排除,将两个新数组进入递归,并且 k 要减去排除的数字的个数。递归出口就是当 k=1 或者其中一个数字长度是 0 了。2.2 代码实现思路1:利用第k小的数来寻找中位数class Solution { private int getKth(int[] nums1, int start1, int end1, int[] nums2, int start2, int end2, int k) { int len1 = end1 - start1 + 1; // 计算数组1的剩余部分的长度 int len2 = end2 - start2 + 1; // 计算数组2的剩余部分的长度 // 递归出口 // 让 len1 的长度小于 len2,这样就能保证如果有数组空了,一定是 len1 if (len1 > len2) return getKth(nums2, start2, end2, nums1, start1, end1, k); // 当其中一个数组都消耗完 if (len1 == 0) return nums2[start2 + k - 1]; // k=1的边界情况 if (k == 1) return Math.min(nums1[start1], nums2[start2]); // 迁移探索k/2 int i = start1 + Math.min(len1, k / 2) - 1; int j = start2 + Math.min(len2, k / 2) - 1; // 缩小探索空间 if (nums1[i] > nums2[j]) { return getKth(nums1, start1, end1, nums2, j + 1, end2, k - (j - start2 + 1)); } else { return getKth(nums1, i + 1, end1, nums2, start2, end2, k - (i - start1 + 1)); } } public double findMedianSortedArrays(int[] nums1, int[] nums2) { int nums1Len = nums1.length; int nums2Len = nums2.length; // 计算中位数的位置 int midLeftIndex = (nums1Len + nums2Len -1) / 2; int midRightIndex = (nums1Len + nums2Len) / 2; // 用寻找第k小的数的算法来找到 中位数的midLeft 和 midRight int midLeft = getKth(nums1, 0, nums1Len - 1, nums2, 0, nums2Len - 1, midLeftIndex+1); int midRight = getKth(nums1, 0, nums1Len - 1, nums2, 0, nums2Len - 1, midRightIndex+1); // 计算中位数 double res = (midLeft+midRight) * 0.5; return res; } public static void main(String[] args) { Solution solution = new Solution(); int[] nums1 = {1,2}; int[] nums2 = {4}; Double res =solution.findMedianSortedArrays(nums1,nums2); System.out.println(res); } }2.3 提交结果提交结果执行用时内存消耗语言提交时间备注通过1 ms42.4 MBJava2022/06/08 21:12添加备注参考资料https://leetcode.cn/problems/median-of-two-sorted-arrayshttps://leetcode.cn/problems/median-of-two-sorted-arrays/solution/xiang-xi-tong-su-de-si-lu-fen-xi-duo-jie-fa-by-w-2/
2022年06月08日
621 阅读
0 评论
0 点赞
2022-06-05
leetcode|中等:43. 字符串相乘
1.题目给定两个以字符串形式表示的非负整数 num1 和 num2,返回 num1 和 num2 的乘积,它们的乘积也表示为字符串形式。示例 1:输入: num1 = "2", num2 = "3" 输出: "6"示例 2:输入: num1 = "123", num2 = "456" 输出: "56088"提示:1 <= num1.length, num2.length <= 200num1 和 num2 只能由数字组成。num1 和 num2 都不包含任何前导零,除了数字0本身。2. 题解2.1 思路分析思路1:题目比较简单 分析乘法运算过程并手动进行模拟即可2.2 代码实现思路1:手动模拟乘法计算过程import java.util.Arrays; class Solution { public String multiply(String num1, String num2) { if(num1.equals("0")||num2.equals("0")){ return "0"; } // 计算res的最大可能长度 int maxResLen = num1.length()*num2.length()+2; int[] res = new int[maxResLen]; for (int i = 0; i < maxResLen; i++) { res[i] = 0; } // String num1 --> num1BitList int[] num1BitList = new int[num1.length()]; for (int i = 0; i < num1.length(); i++) { num1BitList[num1.length()-1-i] = num1.charAt(num1.length()-1-i)-'0'; } // String num2 --> num2BitList int[] num2BitList = new int[num2.length()]; for (int i = 0; i < num2.length(); i++) { num2BitList[num2.length()-1-i] = num2.charAt(num2.length()-1-i)-'0'; } // cal num1 * num2 for (int i = 0; i < num1.length(); i++) { for (int j = 0; j < num2.length(); j++) { res[maxResLen-1-i-j] += num1BitList[num1.length()-1-i]*num2BitList[num2.length()-1-j]; } } // handle bit overflow for (int i = maxResLen-1; i >= 0; i--) { int tmp = res[i]; res[i] = 0; int offset = 0; while (tmp>0){ res[i-offset] += tmp%10; offset++; tmp/=10; } } // int[] res --> String StringBuilder sb = new StringBuilder(); boolean beginFlag = false; for (int i = 0; i < maxResLen; i++) { if(res[i]==0&&beginFlag==false){ continue; }else { beginFlag = true; } sb.append(res[i]); } return sb.toString(); } public static void main(String[] args) { Solution solution = new Solution(); String num1 = "123"; String num2 = "456"; String res =solution.multiply(num1,num2); System.out.println(res); } }2.3 提交结果提交结果执行用时内存消耗语言提交时间备注通过3 ms41.4 MBJava2022/06/05 21:01添加备注参考资料https://leetcode.cn/problems/multiply-strings/
2022年06月05日
461 阅读
0 评论
0 点赞
2022-04-27
leetcode|中等:36. 有效的数独
1.题目请你判断一个 9 x 9 的数独是否有效。只需要 根据以下规则 ,验证已经填入的数字是否有效即可。数字 1-9 在每一行只能出现一次。数字 1-9 在每一列只能出现一次。数字 1-9 在每一个以粗实线分隔的 3x3 宫内只能出现一次。(请参考示例图)注意:一个有效的数独(部分已被填充)不一定是可解的。只需要根据以上规则,验证已经填入的数字是否有效即可。空白格用 '.' 表示。示例 1:输入:board = [["5","3",".",".","7",".",".",".","."] ,["6",".",".","1","9","5",".",".","."] ,[".","9","8",".",".",".",".","6","."] ,["8",".",".",".","6",".",".",".","3"] ,["4",".",".","8",".","3",".",".","1"] ,["7",".",".",".","2",".",".",".","6"] ,[".","6",".",".",".",".","2","8","."] ,[".",".",".","4","1","9",".",".","5"] ,[".",".",".",".","8",".",".","7","9"]] 输出:true示例 2:输入:board = [["8","3",".",".","7",".",".",".","."] ,["6",".",".","1","9","5",".",".","."] ,[".","9","8",".",".",".",".","6","."] ,["8",".",".",".","6",".",".",".","3"] ,["4",".",".","8",".","3",".",".","1"] ,["7",".",".",".","2",".",".",".","6"] ,[".","6",".",".",".",".","2","8","."] ,[".",".",".","4","1","9",".",".","5"] ,[".",".",".",".","8",".",".","7","9"]] 输出:false 解释:除了第一行的第一个数字从 5 改为 8 以外,空格内其他数字均与 示例1 相同。 但由于位于左上角的 3x3 宫内有两个 8 存在, 因此这个数独是无效的。提示:board.length == 9board[i].length == 9board[i][j] 是一位数字(1-9)或者 '.'2. 题解2.1 思路分析思路1:题目比较简单 暴力遍历即可2.2 代码实现思路1:class Solution { public boolean isValidSudoku(char[][] board) { // 0.计数数组 int[] counter = new int[9]; // 1.数字 1-9 在每一行只能出现一次。 for (int i = 0; i < 9; i++) { Arrays.fill(counter,0); for (int j = 0; j < 9; j++) { if(board[i][j]!='.'){ int index = board[i][j]-'1'; counter[index]++; if(counter[index]>1){ return false; } } } } // 2.数字 1-9 在每一列只能出现一次。 for (int i = 0; i < 9; i++) { Arrays.fill(counter,0); for (int j = 0; j < 9; j++) { if(board[j][i]!='.'){ int index = board[j][i]-'1'; counter[index]++; if(counter[index]>1){ return false; } } } } // 3.数字 1-9 在每一个以粗实线分隔的 3x3 宫内只能出现一次。 for (int i = 0; i < 3; i++) { for (int j = 0; j < 3; j++) { Arrays.fill(counter,0); int x_offset = 3*i; int y_offset = 3*j; for (int k = 0; k < 3; k++) { for (int l = 0; l < 3; l++) { if(board[x_offset+k][y_offset+l]!='.'){ int index = board[x_offset+k][y_offset+l]-'1'; counter[index]++; if(counter[index]>1){ return false; } } } } } } return true; } }2.3 提交结果提交结果执行用时内存消耗语言提交时间备注通过1 ms40.8 MBJava2022/04/27 19:31添加备注参考资料https://leetcode-cn.com/problems/valid-sudoku/
2022年04月27日
674 阅读
0 评论
0 点赞
2022-04-27
leetcode|中等:31. 下一个排列
1.题目整数数组的一个 排列 就是将其所有成员以序列或线性顺序排列。例如,arr = [1,2,3] ,以下这些都可以视作 arr 的排列:[1,2,3]、[1,3,2]、[3,1,2]、[2,3,1] 。整数数组的 下一个排列 是指其整数的下一个字典序更大的排列。更正式地,如果数组的所有排列根据其字典顺序从小到大排列在一个容器中,那么数组的 下一个排列 就是在这个有序容器中排在它后面的那个排列。如果不存在下一个更大的排列,那么这个数组必须重排为字典序最小的排列(即,其元素按升序排列)。例如,arr = [1,2,3] 的下一个排列是 [1,3,2] 。类似地,arr = [2,3,1] 的下一个排列是 [3,1,2] 。而 arr = [3,2,1] 的下一个排列是 [1,2,3] ,因为 [3,2,1] 不存在一个字典序更大的排列。给你一个整数数组 nums ,找出 nums 的下一个排列。必须 原地 修改,只允许使用额外常数空间。2. 题解2.1 思路分析思路1: 1.倒序遍历数组, 找到第一个前一个数比后一个数小的位置(即nums[i] < nums[i+1]); firstIndex = i 2.这个时候我们不能直接把后一个数nums[i+1] 跟前一个数nums[i]交换就完事了; 还应该从nums[i+1]-->数组末尾这一段的数据中 找出最优的那个值 如何最优? 即比nums[i]稍微大那么一丢丢的数, 也就是 nums[i+1]-->数组末尾中, 比nums[i]大的数中最小的那个值 下标记为secondeIndex 3.找到之后, 跟num[i]交换, 这还不算是下一个排列, num[i]后面的数值还不够小, 所以还应当对 nums[i+1]-->数组末尾 进升序排列 eg:nums = [1,2,7,4,3,1], 1.倒序遍历数组, 找出第一组 前一个数比后一个数小的两个数 即[2,7] 2.2所处的这个位置就是需要找出比它稍微大的数的位置; 3.我们从[7,4,3,1]中找出比2大的数中的最小值, 也就是3, 找到后跟2交换即可; 当然了, 如果没找到的话, 直接跳到第5步, 直接升序排列输出. 4.目前nums=[1,3,7,4,2,1], 明显可以看出来还不算下一个排列 5.对3后面的数, 升序排列, 即最终结果: nums = [1,3,1,2,4,7]2.2 代码实现思路1:import java.util.*; public class Solution { public void nextPermutation(int[] nums) { // 1.倒序遍历数组,找到第一个满足nums[i] < nums[i+1]的位置 for (int firstIndex = nums.length-2; firstIndex >=0; firstIndex--) { if(nums[firstIndex]<nums[firstIndex+1]){ int secondeIndex = firstIndex+1; // 2.在 nums[i+1]-->数组末尾 找比nums[i]大的数中最小的那个值 for (int i = secondeIndex+1; i < nums.length; i++) { if(nums[i]>nums[firstIndex]&&nums[i]<nums[secondeIndex]){ secondeIndex = i; } } // 3.交换nums[firstIndex]和nums[secondeIndex] int temp = nums[secondeIndex]; nums[secondeIndex] = nums[firstIndex]; nums[firstIndex] = temp; // 4.对nums[firstIndex+1]之后的数进行升序排列 Arrays.sort(nums,firstIndex+1,nums.length); return; } } // 5.如果没找到直接升序排列并返回 Arrays.sort(nums); return; } public static void main(String[] args) { Solution solution = new Solution(); int[] nums = new int[]{1,3,2}; solution.nextPermutation(nums); System.out.println(Arrays.toString(nums)); } } 2.3 提交结果提交结果执行用时内存消耗语言提交时间备注通过1 ms41.8 MBJava2022/04/27 18:36添加备注参考资料https://leetcode-cn.com/problems/next-permutation/
2022年04月27日
657 阅读
0 评论
0 点赞
1
2
...
4