力扣刷题篇之分治

系列文章目录


目录

系列文章目录

前言

一、分解问题

二、解决子问题

三、合并结果

总结


前言

刷题按照:

[力扣刷题攻略] Re:从零开始的力扣刷题生活 - 力扣(LeetCode)

参考:

「五大常用算法」一文搞懂分治算法 - 知乎 (zhihu.com)

分治算法(divide and conquer)是五大常用算法(分治算法、动态规划算法、贪心算法、回溯法、分治界限法)之一,分治,字面上的解释是“分而治之”,就是把一个复杂的问题分成两个或更多的相同或相似的子问题,再把子问题分成更小的子问题……直到最后子问题可以简单的直接求解,原问题的解即子问题的解的合并。在计算机科学中,分治法就是运用分治思想的一种很重要的算法。分治法是很多高效算法的基础,如排序算法(快速排序,归并排序),傅立叶变换(快速傅立叶变换)等等。


一、分解问题

169. 多数元素 - 力扣(LeetCode)

//方法一:排序取中值
// class Solution {
//     public int majorityElement(int[] nums) {
//         Arrays.sort(nums);
//         return nums[nums.length/2];
//     }
// }//方法二:投票法,众数的个数大于n/2,顾投票总数大于0
// class Solution {
//     public int majorityElement(int[] nums) {
//         int count = 0;
//         Integer mode = null;//         for(int num : nums)
//         {
//             if(count == 0)
//             {
//                 mode = num;
//             }
//             count += (num == mode) ? 1 : -1;
//         }
//         return mode;
//     }
// }//方法三:HashMap,数组元素作为键值对的Key,出现个数作为键值对的Value,存放时出现相同的Key,将对应Value进行加1后放到
//HashMap中,遍历数据完成后返回Value值大于n/2的即可。
// class Solution {
//     public int majorityElement(int[] nums) {
//         Map<Integer, Integer> countMap = new HashMap<> ();
//         for(int num : nums)
//         {
//             if(!countMap.containsKey(num))
//             {
//                 countMap.put(num, 1);
//             }
//             else
//             {
//                 countMap.put(num, countMap.get(num) + 1);
//             }//             if(countMap.get(num) > nums.length / 2)
//             {
//                 return num;
//             }
//         }
//         return -1;
//     }
// }// //方法四:回调投票
class Solution {public int majorityElement(int[] nums) {return moore(0, nums, nums[0]);}public int moore(int i, int[] nums, int mode){int count = 0;for(int j = i; j < nums.length; j++){if(nums[j] == mode){count++;}else{count--;}if(count < 0){return moore(j, nums, nums[j]);}}return mode;}
}

4. 寻找两个正序数组的中位数 - 力扣(LeetCode)

class Solution {public double findMedianSortedArrays(int[] nums1, int[] nums2) {int totalLength = nums1.length + nums2.length;int halfLength = totalLength / 2;if (totalLength % 2 == 0) {// 如果总长度是偶数,中位数是左侧部分的最大值和右侧部分的最小值之和的一半double leftMedian = findKthElement(nums1, 0, nums2, 0, halfLength);double rightMedian = findKthElement(nums1, 0, nums2, 0, halfLength + 1);return (leftMedian + rightMedian) / 2.0;} else {// 如果总长度是奇数,中位数就是右侧部分的最小值return findKthElement(nums1, 0, nums2, 0, halfLength + 1);}}private double findKthElement(int[] nums1, int start1, int[] nums2, int start2, int k) {if (start1 == nums1.length) {// 如果 nums1 部分已经为空,则直接返回 nums2 部分的第 k 个元素return nums2[start2 + k - 1];}if (start2 == nums2.length) {// 如果 nums2 部分已经为空,则直接返回 nums1 部分的第 k 个元素return nums1[start1 + k - 1];}if (k == 1) {// 如果 k 等于 1,则直接返回两个数组当前部分的最小值return Math.min(nums1[start1], nums2[start2]);}// 在两个数组中寻找第 k/2 个元素,并更新两个数组的起始位置int mid1 = start1 + k / 2 - 1 < nums1.length ? nums1[start1 + k / 2 - 1] : Integer.MAX_VALUE;int mid2 = start2 + k / 2 - 1 < nums2.length ? nums2[start2 + k / 2 - 1] : Integer.MAX_VALUE;if (mid1 < mid2) {// 如果 nums1 的中间元素小于 nums2 的中间元素,则舍弃 nums1 的左侧部分return findKthElement(nums1, start1 + k / 2, nums2, start2, k - k / 2);} else {// 如果 nums1 的中间元素大于等于 nums2 的中间元素,则舍弃 nums2 的左侧部分return findKthElement(nums1, start1, nums2, start2 + k / 2, k - k / 2);}}
}

543. 二叉树的直径 - 力扣(LeetCode)

/*** Definition for a binary tree node.* public class TreeNode {*     int val;*     TreeNode left;*     TreeNode right;*     TreeNode() {}*     TreeNode(int val) { this.val = val; }*     TreeNode(int val, TreeNode left, TreeNode right) {*         this.val = val;*         this.left = left;*         this.right = right;*     }* }*/
class Solution {int max = 0;public int diameterOfBinaryTree(TreeNode root) {if (root == null) {return 0;}dfs(root);return max;}private int dfs(TreeNode root) {if (root.left == null && root.right == null) {return 0;}int leftSize = root.left == null? 0: dfs(root.left) + 1;int rightSize = root.right == null? 0: dfs(root.right) + 1;max = Math.max(max, leftSize + rightSize);return Math.max(leftSize, rightSize);}  
}

二、解决子问题

69. x 的平方根 - 力扣(LeetCode)

牛顿迭代法:Integer square root - Wikipedia

class Solution {public int mySqrt(int x) {if (x == 0) {return 0;}double x0 = x; // 初始猜测值double x1 = 0.5 * (x0 + x / x0); // 使用牛顿迭代法更新猜测值// 迭代直到猜测值不再变化while (Math.abs(x1 - x0) >= 1) {x0 = x1;x1 = 0.5 * (x0 + x / x0);}return (int) x1; // 将最终结果转换为整数并返回}
}

一个特殊的方法来计算平方根,即通过取指数和对数的方式。实际上,这是一种常见的近似计算方法。它的基本思想是,计算 x 的平方根,可以转换为计算 e^(0.5 * ln(x))。在这里,Math.exp(0.5 * Math.log(x)) 计算的是 e^(0.5 * ln(x))。 

class Solution {public int mySqrt(int x) {if (x == 0) {return 0;}int ans = (int) Math.exp(0.5 * Math.log(x));return (long) (ans + 1) * (ans + 1) <= x ? ans + 1 : ans;}
}

 53. 最大子数组和 - 力扣(LeetCode)

class Solution {public int maxSubArray(int[] nums) {int ans = Integer.MIN_VALUE;int count = 0;for (int i=0; i<nums.length; i++) {count = Math.max(count + nums[i], nums[i]);ans = Math.max(ans, count);}return ans;}
}

34. 在排序数组中查找元素的第一个和最后一个位置 - 力扣(LeetCode)

class Solution {public int[] searchRange(int[] nums, int target) {int[] res = {-1, -1};// 寻找第一个出现的位置int left = 0, right = nums.length - 1;while (left <= right) {int mid = left + (right - left) / 2;if (nums[mid] == target) {res[0] = mid;right = mid - 1; // 继续在左半边搜索} else if (nums[mid] < target) {left = mid + 1;} else {right = mid - 1;}}// 如果未找到目标值,直接返回if (res[0] == -1) {return res;}// 寻找最后一个出现的位置left = res[0]; // 左边界从第一次找到的位置开始right = nums.length - 1;while (left <= right) {int mid = left + (right - left) / 2;if (nums[mid] == target) {res[1] = mid;left = mid + 1; // 继续在右半边搜索} else if (nums[mid] < target) {left = mid + 1;} else {right = mid - 1;}}return res;}
}

三、合并结果

23. 合并 K 个升序链表 - 力扣(LeetCode)

/*** Definition for singly-linked list.* public class ListNode {*     int val;*     ListNode next;*     ListNode() {}*     ListNode(int val) { this.val = val; }*     ListNode(int val, ListNode next) { this.val = val; this.next = next; }* }*/
class Solution {// 合并两个有序链表public ListNode mergeKLists(ListNode[] lists) {if (lists.length == 0) {return null;}return split(lists, 0, lists.length - 1);}public ListNode split(ListNode[] lists, int i, int j) {
//        System.out.println(i + " " + j);if (j == i) {return lists[i];}int m = (i + j) >>> 1;return mergeTwoLists(split(lists, i, m),split(lists, m + 1, j));}public ListNode mergeTwoLists(ListNode p1, ListNode p2) {if (p2 == null || p1 == null) {return p2 == null ? p1 : p2;}if (p1.val < p2.val) {p1.next = mergeTwoLists(p1.next, p2);return p1;} else {p2.next = mergeTwoLists(p1, p2.next);return p2;}}
}

1277. 统计全为 1 的正方形子矩阵 - 力扣(LeetCode)

动态规划 

    class Solution {public int countSquares(int[][] matrix) {// 动态规划, 二维数组dp[i][j]表示以i,j为右下角的最大的全1正方形的边长// if matrix[i][j] == '1' -> dp[i][j] = Min{dp[i - 1][j - 1], dp[i - 1][j], dp[i][j - 1]} + 1int m = matrix.length;int n = matrix[0].length;int[][] dp = new int[m][n];// 初始化边界int result = 0;for (int i = 0; i < m; i++) {if (matrix[i][0] == 1) {dp[i][0] = 1;}}for (int i = 0; i < n; i++) {if (matrix[0][i] == 1) {dp[0][i] = 1;}}// 自底向上for (int i = 1; i < m; i++) {for (int j = 1; j < n; j++) {if (matrix[i][j] == 0) {dp[i][j] = 0;} else {dp[i][j] = Math.min(dp[i - 1][j - 1], Math.min(dp[i - 1][j], dp[i][j - 1])) + 1;}}}// 遍历dpfor (int i = 0; i < m; i++) {for (int j = 0; j < n; j++) {result += dp[i][j];}}return result;}}

 


总结

分治法很重要,然后我发现做题勾勾画画还挺有用的,希望多敲多做,慢慢来吧。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/183210.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

大数据HCIE成神之路之数学(4)——最优化实验

最优化实验 1.1 最小二乘法实现1.1.1 算法介绍1.1.2 代码实现1.2 梯度下降法实现1.2.1 算法介绍1.2.2 代码实现1.3 拉格朗日乘子法1.3.1 实验1.3.2 实验操作步骤1.1 最小二乘法实现 1.1.1 算法介绍 最小二乘法(Least Square Method),做为分类回归算法的基础,有着悠久的历…

第20章:多线程

20.1 线程简介 在Java中&#xff0c;并发机制非常重要&#xff0c;程序员可以在程序中执行多个线程&#xff0c;每个线程完成一个功能&#xff0c;并与其他线程并发执行&#xff0c;这种机制被称为多线程。但是&#xff0c;并不是所有编程语言都支持多线程。 线程的特点&#…

visual studio 2022 更改字体和大小

工具--->选项 文本编辑器 输出窗口

Linux系统之uptime命令的基本使用

Linux系统之uptime命令的基本使用 一、uptime介绍二、uptime命令使用帮助2.1 uptime的help帮助信息2.2 uptime的语法解释 三、uptime的基本使用3.1 直接使用uptime命令3.2 显示uptime版本信息3.3 显示系统运行时间3.4 显示系统最后一次启动时间 四、uptime命令的使用注意事项 一…

基于YOLOv8深度学习的生活垃圾分类目标检测系统【python源码+Pyqt5界面+数据集+训练代码】目标检测

《博主简介》 小伙伴们好&#xff0c;我是阿旭。专注于人工智能、AIGC、python、计算机视觉相关分享研究。 ✌更多学习资源&#xff0c;可关注公-仲-hao:【阿旭算法与机器学习】&#xff0c;共同学习交流~ &#x1f44d;感谢小伙伴们点赞、关注&#xff01; 《------往期经典推…

C++前缀和算法的应用:优化了6版的1324模式

本文涉及的基础知识点 C算法&#xff1a;前缀和、前缀乘积、前缀异或的原理、源码及测试用例 包括课程视频 本题其它解法 C前缀和算法的应用&#xff1a;统计上升四元组 类似题解法 包括题目及代码C二分查找算法&#xff1a;132 模式解法一枚举3C二分查找算法&#xff1a;…

k8s中Pod控制器简介,ReplicaSet、Deployment、HPA三种处理无状态pod应用的控制器介绍

目录 一.Pod控制器简介 二.ReplicaSet&#xff08;简写rs&#xff09; 1.简介 &#xff08;1&#xff09;主要功能 &#xff08;2&#xff09;rs较完整参数解释 2.创建和删除 &#xff08;1&#xff09;创建 &#xff08;2&#xff09;删除 3.扩容和缩容 &#xff08…

vuepress-----7、发布在GitHub

# 7、发布在GitHub 在你的项目中&#xff0c;创建一个如下的 deploy.sh 文件&#xff08;请自行判断去掉高亮行的注释&#xff09;: #!/usr/bin/env sh# 确保脚本抛出遇到的错误 set -e# 生成静态文件 npm run docs:build# 进入生成的文件夹 cd docs/.vuepress/dist# 如果是发…

WebUI自动化学习(Selenium+Python+Pytest框架)004

接下来&#xff0c;WebUI基础知识最后一篇。 1.下拉框操作 关于下拉框的处理有两种方式 &#xff08;1&#xff09;按普通元素定位 安装普通元素的定位方式来定位下拉框&#xff0c;使用元素的操作方法element.click()方法来操作下拉框内容的选择 &#xff08;2&#xff09…

PCB设计注意事项

四个二极管不能省略 pwm波跟电机频率不要是倍频 运放越靠近取样电阻越好 反向输入端跟输出端很敏感&#xff0c;有寄生电容就容易震荡 距离取样电阻近就会距离单片机远&#xff0c;那么线上会有寄生电容&#xff0c;这时候在输出端接一个10k电阻到地

深度学习-模型调试经验总结

1、 这句话的意思是&#xff1a;期望张量的后端处理是在cpu上&#xff0c;但是实际是在cuda上。排查代码发现&#xff0c;数据还在cpu上&#xff0c;但是模型已经转到cuda上&#xff0c;所以可以通过把数据转到cuda上解决。 解决代码&#xff1a; tensor.to("cuda")…

Redis 入门和环境搭建

认识Redis Redis是一种NoSQL数据库&#xff0c;以键值对形式存储数据&#xff0c;支持多种数据结构&#xff0c;包括字符串、哈希、列表、集合、有序集合等&#xff0c;使其适用于多种应用场景。由于所有数据都存储在内存中&#xff0c;Redis的读写性能非常高。同时&#xff0…

安网AC智能路由系统actpt_5g.data敏感信息泄露漏洞复现 [附POC]

文章目录 安网AC智能路由系统actpt_5g.data敏感信息泄露漏洞复现 [附POC]0x01 前言0x02 漏洞描述0x03 影响版本0x04 漏洞环境0x05 漏洞复现1.访问漏洞环境2.构造POC3.复现 安网AC智能路由系统actpt_5g.data敏感信息泄露漏洞复现 [附POC] 0x01 前言 免责声明&#xff1a;请勿利…

面试:说一下深拷贝,浅拷贝,引用拷贝吧;Object类中的clone是哪种呢?

目录 深拷贝、浅拷贝、引用拷贝Object类的clone()方法 深拷贝、浅拷贝、引用拷贝 ● 浅拷贝&#xff1a; 对基本数据类型进行值传递&#xff1b; 对引用类型&#xff0c;复制了一份引用类型的变量 里面存储的内存地址一样 指向的对象也一样。 ● 深拷贝&#xff1a;对基本数据…

kettle入门教程

一、概述 1.什么是kettle Kettle是一款开源的ETL(Extract-Transform-Load)工具&#xff0c;纯java编写&#xff0c;可以在Window、Linux、Unix上运行&#xff0c;绿色无需安装&#xff0c;数据抽取高效稳定。 2.kettle工程存储方式 &#xff08;1&#xff09;以XML形式存储 …

数据结构树与二叉树(5)Huffman树

#include <iostream> #include <stack> #include <queue>using namespace std;struct Node {char name ;int code[200];int num 0;//code的下标int weight 0;//权重&#xff08;次数&#xff09;Node* lchild;//左孩子Node* rchild;//右孩子Node* parent;N…

力扣 --- 三数之和

目录 题目描述&#xff1a; 思路描述&#xff1a; 代码&#xff1a; 提交结果&#xff1a; 官方代码&#xff1a; 官方提交结果&#xff1a; 题目描述&#xff1a; 给你一个整数数组 nums &#xff0c;判断是否存在三元组 [nums[i], nums[j], nums[k]] 满足 i ! j、i ! k…

使用STM32 HAL库驱动烟雾传感器的设计和优化

STM32 HAL库是STMicroelectronics提供的针对STM32系列微控制器的一套硬件抽象层库&#xff0c;可以简化开发过程并提供对各种外设的支持。本文将介绍如何使用STM32 HAL库来驱动烟雾传感器&#xff0c;并对传感器数据采集和处理进行优化。将包括HAL库的初始化、模拟信号采集、数…

UE5、CesiumForUnreal实现加载GeoJson绘制多面(MultiPolygon)功能(支持点选高亮)

文章目录 1.实现目标2.实现过程2.1 数据与预处理2.2 GeoJson解析2.3 Mesh构建与属性存储2.4 核心代码2.5 材质2.6 蓝图应用测试3.参考资料1.实现目标 在之前的文章中,基于GeoJson数据加载,实现了绘制单面功能,但只支持单个要素Feature。本文这里实现对Geojson内所有面要素的…

Abaqus飞机起落架扭力臂拓扑优化

Abaqus飞机起落架扭力臂拓扑优化 Abaqus除了可以对结构进行强度分析&#xff0c;同样也自带强大的优化功能&#xff0c;下面通过一个简 单的实例演示在Abaqus中进行拓扑优化&#xff0c;另外&#xff0c;如果需要更加强大的拓扑优化仿真&#xff0c;可以 在TOSCA中进行。 定义接…