69. Sqrt(x)(分治)

本文介绍了一种使用二分法来求解整数平方根的方法,并提供了完整的Java实现代码。该方法的时间复杂度为O(lgN),适用于快速求解大整数的平方根问题。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

题目:

Implement int sqrt(int x).

Compute and return the square root of x.

求平方根,用二分法,时间复杂度为O(lgN)

代码:

public class Solution {
    public int mySqrt(int x) {
        if(x<2)return x;
        int left =1,right=x/2,last_mid=0;
        while(left<=right)
        {
        	int mid= left+(right-left)/2;
        	if(x/mid<mid)
        	{
        		right=mid-1;
//        		last_mid=mid;
        	}
        	else if(x/mid>mid)
        	{
        		left=mid+1;
        		//如果未能找到相等的,去小于该值的平方根
        		last_mid=mid; 
        	}
        	else
        	{
        		return mid;
        	}
        }
        return last_mid;
    }
}


import time, os, math, gc from media.sensor import * from media.display import * from media.media import * from machine import FPIOA, UART, TOUCH, Pin # 图像参数 - 使用320x240标准分辨率 IMAGE_WIDTH = 320 IMAGE_HEIGHT = 240 SENSOR_ID = 2 sensor = None THRESHOLD = (69, 252) # 初始灰度阈值 # 显示模式设置 DISPLAY_MODE = "LCD" # 可选 "VIRT", "LCD", "HDMI" # 根据显示模式设置分辨率 if DISPLAY_MODE == "VIRT": DISPLAY_WIDTH, DISPLAY_HEIGHT = 320, 240 elif DISPLAY_MODE == "LCD": DISPLAY_WIDTH, DISPLAY_HEIGHT = 320, 240 elif DISPLAY_MODE == "HDMI": DISPLAY_WIDTH, DISPLAY_HEIGHT = 320, 240 else: raise ValueError("无效的显示模式") # 角点检测阈值 CORNERS_THRESHOLD = 5000 # 透视变换目标尺寸 PERSPECTIVE_SIZE = 200 # 变换后的矩形大小 # 矩形过滤参数 MIN_AREA_RATIO = 0.01 # 最小面积占图像比例 MAX_AREA_RATIO = 0.8 # 最大面积占图像比例 ASPECT_RATIO_MIN = 0.5 # 最小宽高比 ASPECT_RATIO_MAX = 2.0 # 最大宽高比 COS_THRESHOLD = 0.3 # 角度余弦阈值(绝对值) # 初始化UART2 fpioa = FPIOA() fpioa.set_function(11, FPIOA.UART2_TXD) # UART2发送 fpioa.set_function(12, FPIOA.UART2_RXD) # UART2接收 uart2 = UART(UART.UART2, 115200, 8, 0, 1, timeout=1000) # 用于坐标通信 # 初始化按键 fpioa.set_function(53, FPIOA.GPIO53) button = Pin(53, Pin.IN, Pin.PULL_DOWN) # 使用下拉电阻 debounce_delay = 20 # 毫秒 last_press_time = 0 # 上次按键按下的时间,单位为毫秒 button_last_state = 0 # 上次按键状态 timeTouch = 0 tp = TOUCH(0) # 按钮文本 (简化版本) textL = ["GL-", "GH-", "Step", "Back"] textR = ["GL+", "GH+", "Invert", " "] isInvertFlag = False # 是否反转 # 虚拟按钮范围 (320x240分辨率下的布局) buttonsL = [ (10, 10, 70, 30), # GL- (10, 50, 70, 30), # GH- (10, 90, 70, 30), # Step (10, 130, 70, 30) # Back ] buttonsR = [ (240, 10, 70, 30), # GL+ (240, 50, 70, 30), # GH+ (240, 90, 70, 30), # Invert (240, 130, 70, 30) # 空按钮 ] # 灰度范围初始化 GL, GH = 0, 255 # 灰度范围0~255 step = 1 # 脱机阈值步进 Gray_thresholds = [(int(GL), int(GH))] # 灰度阈值列表 # 状态标志 flag = False # 页面标志,True为阈值设置 # 脱机调整阈值界面设计 (优化版本) def changeScreen(img): # 直接处理灰度图像,避免闪白 GrayImg = img.to_grayscale().binary(Gray_thresholds) if isInvertFlag: GrayImg = GrayImg.invert() # 创建屏幕图像 screen = GrayImg.copy() # 绘制按钮 for i in range(4): # 左侧按钮 screen.draw_rectangle(buttonsL[i][0], buttonsL[i][1], buttonsL[i][2], buttonsL[i][3], (200, 201, 202), thickness=1, fill=True) screen.draw_string(buttonsL[i][0] + 5, buttonsL[i][1] + 10, textL[i], color=(0, 0, 0), scale=1) # 右侧按钮 screen.draw_rectangle(buttonsR[i][0], buttonsR[i][1], buttonsR[i][2], buttonsR[i][3], (200, 201, 202), thickness=1, fill=True) screen.draw_string(buttonsR[i][0] + 5, buttonsR[i][1] + 10, textR[i], color=(0, 0, 0), scale=1) # 显示阈值和步进信息 screen.draw_string(100, 180, f"GL: {GL} GH: {GH}", color=(255, 255, 255) if isInvertFlag else (0, 0, 0), scale=1) screen.draw_string(100, 200, f"Step: {step}", color=(255, 255, 255) if isInvertFlag else (0, 0, 0), scale=1) # 显示处理后的图像 Display.show_image(screen, 0, 0, DISPLAY_WIDTH, DISPLAY_HEIGHT) # 触摸屏按钮事件动作 def buttonAction(direction, index): global GL, GH, flag, step, isInvertFlag, textR, Gray_thresholds # 阈值列表重置 Gray_thresholds = [(int(GL), int(GH))] # 按钮处理 if direction == 'left': if index == 0: # GL- GL = max(GL - step, 0) elif index == 1: # GH- GH = max(GH - step, 0) elif index == 2: # Step step = step + 1 if step < 5 else 1 elif index == 3: # Back flag = False elif direction == 'right': if index == 0: # GL+ GL = min(GL + step, 255) elif index == 1: # GH+ GH = min(GH + step, 255) elif index == 2: # Invert isInvertFlag = not isInvertFlag textR[2] = 'Normal' if isInvertFlag else 'Invert' # 触摸屏事件 def touchAction(): global timeTouch touchP = tp.read(2) if touchP: timeTouch += 1 if timeTouch >= 3: p = touchP timeTouch = 0 if p: x, y = p[0].x, p[0].y # 检查左侧按钮 for i, rect in enumerate(buttonsL): if (rect[0] <= x <= rect[0] + rect[2] and rect[1] <= y <= rect[1] + rect[3]): buttonAction('left', i) return # 检查右侧按钮 for i, rect in enumerate(buttonsR): if (rect[0] <= x <= rect[0] + rect[2] and rect[1] <= y <= rect[1] + rect[3]): buttonAction('right', i) return # 发送坐标函数 def send_coordinates(center): """通过串口发送坐标数据""" if center: cx, cy = center # 协议格式: $X[坐标x]Y[坐标y]\n data_str = f"$X{cx:04d}Y{cy:04d}\n" uart2.write(data_str.encode()) else: uart2.write(b"$X9999Y9999\n") # 无效坐标标志 # 角点排序函数 def sort_corners(corners): """对矩形角点进行排序(左上、右上、右下、左下)""" if len(corners) != 4: return corners # 计算中心点 center_x = sum(c[0] for c in corners) / 4 center_y = sum(c[1] for c in corners) / 4 # 分类角点 def distance_to_center(corner): return (corner[0] - center_x)**2 + (corner[1] - center_y)**2 top_left = min(corners, key=lambda c: distance_to_center(c) if c[0] < center_x and c[1] < center_y else float('inf')) top_right = min(corners, key=lambda c: distance_to_center(c) if c[0] > center_x and c[1] < center_y else float('inf')) bottom_right = min(corners, key=lambda c: distance_to_center(c) if c[0] > center_x and c[1] > center_y else float('inf')) bottom_left = min(corners, key=lambda c: distance_to_center(c) if c[0] < center_x and c[1] > center_y else float('inf')) return [top_left, top_right, bottom_right, bottom_left] # 矩形有效性检查 def is_valid_rectangle(corners, cos_threshold=COS_THRESHOLD): """ 检查是否为有效矩形(内角接近90度) corners: 排序后的四个角点 [左上, 右上, 右下, 左下] cos_threshold: 余弦值阈值(绝对值应小于此值) 返回: True/False """ if len(corners) != 4: return False # 计算四个内角的余弦值 for i in range(4): # 获取三个连续点: A-B-C A = corners[i] B = corners[(i + 1) % 4] C = corners[(i + 2) % 4] # 计算向量BA和BC BA = (A[0] - B[0], A[1] - B[1]) BC = (C[0] - B[0], C[1] - B[1]) # 计算点积和模长 dot_product = BA[0] * BC[0] + BA[1] * BC[1] mod_BA = math.sqrt(BA[0]**2 + BA[1]**2) mod_BC = math.sqrt(BC[0]**2 + BC[1]**2) # 避免除零错误 if mod_BA * mod_BC < 1e-5: return False # 计算余弦值 cos_value = dot_product / (mod_BA * mod_BC) # 检查是否接近90度 (|cos| < threshold) if abs(cos_value) > cos_threshold: return False return True # 矩形属性计算 def calculate_rect_properties(corners): """计算矩形的面积和宽高比""" if len(corners) != 4: return 0, 0 # 计算边长 top = math.sqrt((corners[1][0] - corners[0][0])**2 + (corners[1][1] - corners[0][1])**2) right = math.sqrt((corners[2][0] - corners[1][0])**2 + (corners[2][1] - corners[1][1])**2) bottom = math.sqrt((corners[3][0] - corners[2][0])**2 + (corners[3][1] - corners[2][1])**2) left = math.sqrt((corners[0][0] - corners[3][0])**2 + (corners[0][1] - corners[3][1])**2) # 计算平均宽度和高度 width = (top + bottom) / 2 height = (left + right) / 2 # 计算面积和宽高比 area = width * height aspect_ratio = max(width, height) / min(width, height) if min(width, height) > 0 else 0 return area, aspect_ratio # 绘制角点信息 def draw_corner_info(img, corners, center, area, aspect_ratio): """在图像上绘制角点和中心信息""" if len(corners) != 4: return # 定义角点颜色和标签 corner_colors = [(0, 255, 0), (0, 255, 0), (0, 255, 0), (0, 255, 0)] labels = ["TL", "TR", "BR", "BL"] # 绘制角点 for i, (x, y) in enumerate(corners): color = corner_colors[i] img.draw_circle(int(x), int(y), 5, color=color, thickness=2) img.draw_string(int(x) + 5, int(y) - 5, labels[i], color=color, scale=1) # 绘制矩形边框 for i in range(4): x1, y1 = corners[i] x2, y2 = corners[(i + 1) % 4] img.draw_line(int(x1), int(y1), int(x2), int(y2), color=(0, 255, 255), thickness=1) # 绘制对角线 img.draw_line(int(corners[0][0]), int(corners[0][1]), int(corners[2][0]), int(corners[2][1]), color=(255, 0, 0), thickness=1) img.draw_line(int(corners[1][0]), int(corners[1][1]), int(corners[3][0]), int(corners[3][1]), color=(255, 0, 0), thickness=1) # 绘制中心点 if center: cx, cy = center img.draw_cross(int(cx), int(cy), size=10, color=(255, 0, 255), thickness=2) img.draw_circle(int(cx), int(cy), 3, color=(255, 0, 255), thickness=-1) img.draw_string(int(cx) + 5, int(cy) - 5, "Center", color=(255, 0, 255), scale=1) # 显示矩形属性 img.draw_string(10, 30, f"Area: {area:.1f} px", color=(0, 255, 0), scale=1) img.draw_string(10, 50, f"Aspect: {aspect_ratio:.2f}", color=(0, 255, 0), scale=1) # 图像处理函数 def process_frame(img): """处理图像帧,检测矩形角点和中心(带形状验证)""" img_gray = img.to_grayscale(copy=False) img_bin = img_gray.binary([(GL, GH)]) rects = img_bin.find_rects(threshold=CORNERS_THRESHOLD) # 计算图像总面积 total_image_area = img.width() * img.height() min_area = MIN_AREA_RATIO * total_image_area max_area = MAX_AREA_RATIO * total_image_area # 找出所有可能的矩形 valid_rects = [] for rect in rects: corners = rect.corners() if len(corners) == 4: sorted_corners = sort_corners(corners) # 计算矩形属性 area, aspect_ratio = calculate_rect_properties(sorted_corners) # 检查角度、面积和宽高比 angle_valid = is_valid_rectangle(sorted_corners) area_valid = min_area <= area <= max_area aspect_valid = ASPECT_RATIO_MIN <= aspect_ratio <= ASPECT_RATIO_MAX if angle_valid and area_valid and aspect_valid: valid_rects.append((area, aspect_ratio, sorted_corners)) # 选择面积最大的有效矩形 corners = [] center = None area = 0 aspect_ratio = 0 if valid_rects: valid_rects.sort(key=lambda x: x[0], reverse=True) area, aspect_ratio, corners = valid_rects[0] # 计算中心点 (简化方法) center_x = sum(c[0] for c in corners) / len(corners) center_y = sum(c[1] for c in corners) / len(corners) center = (int(center_x), int(center_y)) # 绘制结果 if center: draw_corner_info(img, corners, center, area, aspect_ratio) else: # 显示未检测到矩形的信息 img.draw_string(img.width()//2 - 50, img.height()//2, "No valid rectangle", color=(255, 0, 0), scale=1) # 资源清理 del img_gray, img_bin gc.collect() return corners, center try: print("初始化摄像头...") # 初始化摄像头 sensor = Sensor(id=SENSOR_ID) sensor.reset() # 设置与显示匹配的分辨率 sensor.set_framesize(width=DISPLAY_WIDTH, height=DISPLAY_HEIGHT) sensor.set_pixformat(Sensor.RGB565, chn=CAM_CHN_ID_0) sensor.set_hmirror(1) sensor.set_vflip(1) print("初始化显示器...") # 初始化显示器 - 修复Display.init调用 if DISPLAY_MODE == "VIRT": Display.init(Display.VIRT, width=DISPLAY_WIDTH, height=DISPLAY_HEIGHT, fps=60) elif DISPLAY_MODE == "LCD": Display.init(Display.ST7701, width=800, height=480) elif DISPLAY_MODE == "HDMI": Display.init(Display.LT9611, width=DISPLAY_WIDTH, height=DISPLAY_HEIGHT) print("初始化媒体管理器...") # 初始化媒体管理器 MediaManager.init() sensor.run() clock = time.clock() print("开始主循环...") while True: os.exitpoint() clock.tick() # 捕获图像 img = sensor.snapshot(chn=CAM_CHN_ID_0) # 处理按键事件 button_state = button.value() # 获取当前按键状态 current_time = time.ticks_ms() # 获取当前时间(单位:毫秒) # 检测按键从未按下(0)到按下(1)的变化(上升沿) if button_state == 1 and button_last_state == 0: # 检查按键是否在消抖时间外 if current_time - last_press_time > debounce_delay: if button.value() == 1: flag = not flag print("进入阈值设置模式" if flag else "退出阈值设置模式") last_press_time = current_time # 更新上次按键状态 button_last_state = button_state # 仅在阈值设置界面显示阈值调整UI if flag: changeScreen(img) touchAction() else: # 正常模式下显示原始图像和处理结果 # 处理图像并检测角点 corners, center = process_frame(img) # 发送坐标 send_coordinates(center) # 显示FPS img.draw_string(10, 10, f"FPS: {clock.fps():.1f}", color=(255, 0, 0), scale=1) # 显示图像(全屏) img.compressed_for_ide() Display.show_image(img, 0, 0, DISPLAY_WIDTH, DISPLAY_HEIGHT) # 控制处理频率 time.sleep_ms(20) except KeyboardInterrupt: print("程序被用户中断") except Exception as e: print(f"发生错误: {e}") import sys sys.print_exception(e) finally: print("清理资源...") # 清理资源 if sensor: sensor.stop() Display.deinit() MediaManager.deinit() print("程序退出") 将上述程序的图像参数修改成合理的最小
最新发布
08-04
综合运用分治算法和动态规划算法,设计并实现一个图像压缩与处理系统,掌握算法在实际问题中的应用。 2. 设计目标 理解图像压缩的基本原理:掌握图像压缩的常见方法,如离散余弦变换(DCT)、哈夫曼编码等。 分治算法的应用:将分治算法应用于图像分割和处理,如图像的分块压缩。 动态规划的应用:使用动态规划算法优化图像压缩过程中的编码选择,如最优分割点的选择。 系统设计与实现:设计并实现一个完整的图像压缩与处理系统,支持图像的压缩、解压缩和基本处理功能。 性能优化与对比:对比不同算法的压缩效果和性能,分析其时间复杂度和空间复杂度。 3. 设计方案 3.1 系统功能需求 图像压缩功能: 支持常见的图像格式(如BMP、PNG等)。 使用分治算法对图像进行分块处理,应用离散余弦变换(DCT)进行压缩。 使用动态规划算法优化压缩过程中的编码选择,如哈夫曼编码。 图像解压缩功能: 支持将压缩后的图像解压缩为原始格式。 使用分治算法和动态规划算法进行解压缩。 图像处理功能: 支持基本的图像处理操作,如图像缩放、旋转、滤波等。 使用分治算法对图像进行分块处理,提高处理效率。 性能测试与分析: 对比不同压缩算法的压缩比和图像质量。 分析不同算法的时间复杂度和空间复杂度。 3.2 设计步骤 图像压缩模块 分治算法的应用:将图像分割为多个小块(如8x8像素),对每个小块应用离散余弦变换(DCT)进行压缩。 动态规划的应用:使用动态规划算法优化哈夫曼编码的选择,确保压缩后的数据量最小。 压缩流程: 图像分块:使用分治算法将图像分割为多个小块。 DCT变换:对每个小块进行DCT变换,将图像从空间域转换到频率域。 量化:对DCT系数进行量化,减少数据量。 哈夫曼编码:使用动态规划算法优化哈夫曼编码,生成压缩后的数据。 图像解压缩模块 分治算法的应用:将压缩后的数据分块解压缩,逐步恢复图像。 解压缩流程: 哈夫曼解码:使用动态规划算法优化哈夫曼解码过程。 反量化:将量化后的DCT系数恢复为原始值。 逆DCT变换:将频率域的DCT系数转换回空间域。 图像重建:将解压缩后的图像块合并为完整的图像。 图像处理模块 分治算法的应用:将图像分割为多个小块,分别进行处理(如滤波、旋转等)。 处理流程: 图像分块:使用分治算法将图像分割为多个小块。 并行处理:对每个小块进行图像处理操作。 图像合并:将处理后的图像块合并为完整的图像。 性能测试与分析模块 压缩比测试:对比不同压缩算法的压缩比,分析压缩效果。 图像质量测试:使用PSNR(峰值信噪比)等指标评估压缩后的图像质量。 时间复杂度分析:分析分治算法和动态规划算法的时间复杂度,对比不同算法的性能。 3.3 实现要求 使用C/C++、Java或Python等编程语言实现图像压缩与处理系统。 编写详细的代码注释,说明算法的每一步操作。 设计测试用例,验证系统的正确性和性能。 3.4 实验报告 问题描述:简要描述图像压缩与处理的基本原理及其应用场景。 系统设计:详细描述系统的架构设计、模块划分以及算法选择。 算法实现:提供分治算法和动态规划算法的实现细节,并附上详细的代码注释。 测试结果:展示不同压缩算法的压缩比、图像质量以及运行时间,分析系统的性能。 总结与反思:总结系统的优缺点,讨论算法的优化效果,并提出进一步改进的思路。 4. 评分标准 系统功能实现(40分):正确实现图像压缩、解压缩和处理功能,代码结构清晰,注释详细。 算法应用与优化(30分):合理应用分治算法和动态规划算法,并进行优化,提高系统效率。 性能测试与分析(20分):设计合理的测试用例,进行性能测试,并分析结果。 实验报告(10分):实验报告内容完整,逻辑清晰,分析深入。 6. 扩展任务(可选) 并行化处理:尝试将分治算法并行化,利用多线程或多进程技术加速图像处理。 其他压缩算法:探索其他图像压缩算法(如JPEG2000、小波变换等),并与分治算法和动态规划算法进行对比。 Python import numpy as np from PIL import Image import math # 分治算法:图像分块 def divide_image(image, block_size): height, width = image.shape blocks = [] for i in range(0, height, block_size): for j in range(0, width, block_size): block = image[i:i+block_size, j:j+block_size] blocks.append(block) return blocks # DCT变换 def dct_transform(block): return np.fft.fft2(block) # 量化 def quantize(block, quantization_table): return np.round(block / quantization_table) # 哈夫曼编码(动态规划优化) def huffman_encode(data): # 动态规划优化哈夫曼编码 pass # 图像压缩 def compress_image(image, block_size=8): blocks = divide_image(image, block_size) compressed_blocks = [] for block in blocks: dct_block = dct_transform(block) quantized_block = quantize(dct_block, quantization_table) encoded_block = huffman_encode(quantized_block) compressed_blocks.append(encoded_block) return compressed_blocks # 图像解压缩 def decompress_image(compressed_blocks, block_size=8): # 解压缩流程 pass # 测试代码 if __name__ == "__main__": # 读取图像 image = np.array(Image.open("input.bmp").convert('L')) # 图像压缩 compressed_blocks = compress_image(image) # 图像解压缩 decompressed_image = decompress_image(compressed_blocks) # 保存解压缩后的图像 Image.fromarray(decompressed_image).save("output.bmp")
05-31
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值